1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665 |
- // Copyright (c) 2012 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.
- #include "net/quic/quic_chromium_client_session.h"
- #include "base/base64.h"
- #include "base/bind.h"
- #include "base/files/file_path.h"
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/strings/strcat.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/default_tick_clock.h"
- #include "build/build_config.h"
- #include "net/base/features.h"
- #include "net/base/network_isolation_key.h"
- #include "net/base/schemeful_site.h"
- #include "net/base/test_completion_callback.h"
- #include "net/cert/cert_verify_result.h"
- #include "net/dns/public/secure_dns_policy.h"
- #include "net/http/transport_security_state.h"
- #include "net/http/transport_security_state_test_util.h"
- #include "net/log/net_log.h"
- #include "net/log/net_log_source.h"
- #include "net/quic/address_utils.h"
- #include "net/quic/crypto/proof_verifier_chromium.h"
- #include "net/quic/mock_crypto_client_stream_factory.h"
- #include "net/quic/mock_quic_data.h"
- #include "net/quic/quic_chromium_alarm_factory.h"
- #include "net/quic/quic_chromium_client_session_peer.h"
- #include "net/quic/quic_chromium_connection_helper.h"
- #include "net/quic/quic_chromium_packet_reader.h"
- #include "net/quic/quic_chromium_packet_writer.h"
- #include "net/quic/quic_connectivity_monitor.h"
- #include "net/quic/quic_crypto_client_config_handle.h"
- #include "net/quic/quic_crypto_client_stream_factory.h"
- #include "net/quic/quic_http_utils.h"
- #include "net/quic/quic_server_info.h"
- #include "net/quic/quic_session_key.h"
- #include "net/quic/quic_test_packet_maker.h"
- #include "net/quic/test_quic_crypto_client_config_handle.h"
- #include "net/socket/datagram_client_socket.h"
- #include "net/socket/socket_test_util.h"
- #include "net/spdy/spdy_test_util_common.h"
- #include "net/test/cert_test_util.h"
- #include "net/test/gtest_util.h"
- #include "net/test/test_data_directory.h"
- #include "net/test/test_with_task_environment.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_12_encrypter.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
- #include "net/third_party/quiche/src/quiche/quic/core/http/quic_client_promised_info.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
- #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_client_promised_info_peer.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_stream_peer.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/simple_quic_framer.h"
- #include "net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h"
- #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "url/gurl.h"
- #include "url/scheme_host_port.h"
- #include "url/url_constants.h"
- using testing::_;
- namespace net::test {
- namespace {
- const IPEndPoint kIpEndPoint = IPEndPoint(IPAddress::IPv4AllZeros(), 0);
- const char kServerHostname[] = "test.example.com";
- const uint16_t kServerPort = 443;
- const size_t kMaxReadersPerQuicSession = 5;
- const handles::NetworkHandle kDefaultNetworkForTests = 1;
- const handles::NetworkHandle kNewNetworkForTests = 2;
- struct TestParams {
- quic::ParsedQuicVersion version;
- bool client_headers_include_h2_stream_dependency;
- };
- // Used by ::testing::PrintToStringParamName().
- std::string PrintToString(const TestParams& p) {
- return base::StrCat(
- {ParsedQuicVersionToString(p.version), "_",
- (p.client_headers_include_h2_stream_dependency ? "" : "No"),
- "Dependency"});
- }
- std::vector<TestParams> GetTestParams() {
- std::vector<TestParams> params;
- quic::ParsedQuicVersionVector all_supported_versions =
- quic::AllSupportedVersions();
- for (const auto& version : all_supported_versions) {
- params.push_back(TestParams{version, false});
- params.push_back(TestParams{version, true});
- }
- return params;
- }
- // A subclass of QuicChromiumClientSession that allows OnPathDegrading to be
- // mocked.
- class TestingQuicChromiumClientSession : public QuicChromiumClientSession {
- public:
- using QuicChromiumClientSession::QuicChromiumClientSession;
- MOCK_METHOD(void, OnPathDegrading, (), (override));
- void ReallyOnPathDegrading() { QuicChromiumClientSession::OnPathDegrading(); }
- };
- class QuicChromiumClientSessionTest
- : public ::testing::TestWithParam<TestParams>,
- public WithTaskEnvironment {
- public:
- QuicChromiumClientSessionTest()
- : version_(GetParam().version),
- client_headers_include_h2_stream_dependency_(
- GetParam().client_headers_include_h2_stream_dependency),
- config_(quic::test::DefaultQuicConfig()),
- crypto_config_(
- quic::test::crypto_test_utils::ProofVerifierForTesting()),
- default_read_(
- std::make_unique<MockRead>(SYNCHRONOUS, ERR_IO_PENDING, 0)),
- socket_data_(std::make_unique<SequencedSocketData>(
- base::make_span(default_read_.get(), 1),
- base::span<MockWrite>())),
- helper_(&clock_, &random_),
- transport_security_state_(std::make_unique<TransportSecurityState>()),
- session_key_(kServerHostname,
- kServerPort,
- PRIVACY_MODE_DISABLED,
- SocketTag(),
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false),
- destination_(url::kHttpsScheme, kServerHostname, kServerPort),
- default_network_(handles::kInvalidNetworkHandle),
- client_maker_(version_,
- quic::QuicUtils::CreateRandomConnectionId(&random_),
- &clock_,
- kServerHostname,
- quic::Perspective::IS_CLIENT,
- client_headers_include_h2_stream_dependency_),
- server_maker_(version_,
- quic::QuicUtils::CreateRandomConnectionId(&random_),
- &clock_,
- kServerHostname,
- quic::Perspective::IS_SERVER,
- false) {
- FLAGS_quic_enable_http3_grease_randomness = false;
- quic::QuicEnableVersion(version_);
- // Advance the time, because timers do not like uninitialized times.
- clock_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
- }
- void ResetHandleOnError(
- std::unique_ptr<QuicChromiumClientSession::Handle>* handle,
- int net_error) {
- EXPECT_NE(OK, net_error);
- handle->reset();
- }
- protected:
- void Initialize() {
- if (socket_data_)
- socket_factory_.AddSocketDataProvider(socket_data_.get());
- std::unique_ptr<DatagramClientSocket> socket =
- socket_factory_.CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource());
- socket->Connect(kIpEndPoint);
- QuicChromiumPacketWriter* writer = new net::QuicChromiumPacketWriter(
- socket.get(), base::ThreadTaskRunnerHandle::Get().get());
- quic::QuicConnection* connection = new quic::QuicConnection(
- quic::QuicUtils::CreateRandomConnectionId(&random_),
- quic::QuicSocketAddress(), ToQuicSocketAddress(kIpEndPoint), &helper_,
- &alarm_factory_, writer, true, quic::Perspective::IS_CLIENT,
- quic::test::SupportedVersions(version_));
- session_ = std::make_unique<TestingQuicChromiumClientSession>(
- connection, std::move(socket),
- /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
- transport_security_state_.get(), /*ssl_config_service=*/nullptr,
- base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), session_key_,
- /*require_confirmation=*/false, migrate_session_early_v2_,
- /*migrate_session_on_network_change_v2=*/false, default_network_,
- quic::QuicTime::Delta::FromMilliseconds(
- kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
- /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
- kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
- kMaxMigrationsToNonDefaultNetworkOnWriteError,
- kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
- kQuicYieldAfterPacketsRead,
- quic::QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- client_headers_include_h2_stream_dependency_,
- /*cert_verify_flags=*/0, config_,
- std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
- "CONNECTION_UNKNOWN", base::TimeTicks::Now(), base::TimeTicks::Now(),
- std::make_unique<quic::QuicClientPushPromiseIndex>(),
- &test_push_delegate_, base::DefaultTickClock::GetInstance(),
- base::ThreadTaskRunnerHandle::Get().get(),
- /*socket_performance_watcher=*/nullptr, NetLog::Get());
- if (connectivity_monitor_) {
- connectivity_monitor_->SetInitialDefaultNetwork(default_network_);
- session_->AddConnectivityObserver(connectivity_monitor_.get());
- }
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
- verify_details_.cert_verify_result.verified_cert = cert;
- verify_details_.cert_verify_result.is_issued_by_known_root = true;
- session_->Initialize();
- // Blackhole QPACK decoder stream instead of constructing mock writes.
- if (VersionUsesHttp3(version_.transport_version)) {
- session_->qpack_decoder()->set_qpack_stream_sender_delegate(
- &noop_qpack_stream_sender_delegate_);
- }
- session_->StartReading();
- writer->set_delegate(session_.get());
- }
- void TearDown() override {
- if (session_) {
- if (connectivity_monitor_)
- session_->RemoveConnectivityObserver(connectivity_monitor_.get());
- session_->CloseSessionOnError(
- ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- }
- }
- void SetIetfConnectionMigrationFlagsAndConnectionOptions() {
- FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2 = true;
- config_.SetConnectionOptionsToSend({quic::kRVCM});
- }
- void CompleteCryptoHandshake() {
- ASSERT_THAT(session_->CryptoConnect(callback_.callback()), IsOk());
- }
- std::unique_ptr<QuicChromiumPacketWriter> CreateQuicChromiumPacketWriter(
- DatagramClientSocket* socket,
- QuicChromiumClientSession* session) const {
- auto writer = std::make_unique<QuicChromiumPacketWriter>(
- socket, base::ThreadTaskRunnerHandle::Get().get());
- writer->set_delegate(session);
- return writer;
- }
- quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
- return quic::test::GetNthClientInitiatedBidirectionalStreamId(
- version_.transport_version, n);
- }
- quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) {
- return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
- version_.transport_version, n);
- }
- size_t GetMaxAllowedOutgoingBidirectionalStreams() {
- quic::QuicSession* quic_session =
- static_cast<quic::QuicSession*>(&*session_);
- if (!version_.HasIetfQuicFrames()) {
- return quic::test::QuicSessionPeer::GetStreamIdManager(quic_session)
- ->max_open_outgoing_streams();
- }
- // For version99, the count will include both static and dynamic streams.
- // These tests are only concerned with dynamic streams (that is, the number
- // of streams that they can create), so back out the static header stream.
- return quic::test::QuicSessionPeer::ietf_streamid_manager(quic_session)
- ->max_outgoing_bidirectional_streams();
- }
- const quic::ParsedQuicVersion version_;
- const bool client_headers_include_h2_stream_dependency_;
- quic::test::QuicFlagSaver flags_; // Save/restore all QUIC flag values.
- quic::QuicConfig config_;
- quic::QuicCryptoClientConfig crypto_config_;
- NetLogWithSource net_log_with_source_{
- NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
- MockClientSocketFactory socket_factory_;
- std::unique_ptr<MockRead> default_read_;
- std::unique_ptr<SequencedSocketData> socket_data_;
- quic::MockClock clock_;
- quic::test::MockRandom random_{0};
- QuicChromiumConnectionHelper helper_;
- quic::test::MockAlarmFactory alarm_factory_;
- std::unique_ptr<TransportSecurityState> transport_security_state_;
- MockCryptoClientStreamFactory crypto_client_stream_factory_;
- QuicSessionKey session_key_;
- url::SchemeHostPort destination_;
- std::unique_ptr<TestingQuicChromiumClientSession> session_;
- handles::NetworkHandle default_network_;
- std::unique_ptr<QuicConnectivityMonitor> connectivity_monitor_;
- TestServerPushDelegate test_push_delegate_;
- raw_ptr<quic::QuicConnectionVisitorInterface> visitor_;
- TestCompletionCallback callback_;
- QuicTestPacketMaker client_maker_;
- QuicTestPacketMaker server_maker_;
- ProofVerifyDetailsChromium verify_details_;
- bool migrate_session_early_v2_ = false;
- quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
- };
- INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
- QuicChromiumClientSessionTest,
- ::testing::ValuesIn(GetTestParams()),
- ::testing::PrintToStringParamName());
- // Basic test of ProofVerifyDetailsChromium is converted to SSLInfo retrieved
- // through QuicChromiumClientSession::GetSSLInfo(). Doesn't test some of the
- // more complicated fields.
- TEST_P(QuicChromiumClientSessionTest, GetSSLInfo1) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.is_fatal_cert_error = false;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.is_issued_by_known_root = true;
- details.cert_verify_result.policy_compliance =
- ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- SSLInfo ssl_info;
- ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
- EXPECT_TRUE(ssl_info.is_valid());
- EXPECT_EQ(details.is_fatal_cert_error, ssl_info.is_fatal_cert_error);
- EXPECT_TRUE(ssl_info.cert->EqualsIncludingChain(
- details.cert_verify_result.verified_cert.get()));
- EXPECT_EQ(details.cert_verify_result.cert_status, ssl_info.cert_status);
- EXPECT_EQ(details.cert_verify_result.is_issued_by_known_root,
- ssl_info.is_issued_by_known_root);
- EXPECT_EQ(details.cert_verify_result.policy_compliance,
- ssl_info.ct_policy_compliance);
- }
- // Just like GetSSLInfo1, but uses different values.
- TEST_P(QuicChromiumClientSessionTest, GetSSLInfo2) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.is_fatal_cert_error = false;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.is_issued_by_known_root = false;
- details.cert_verify_result.policy_compliance =
- ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- SSLInfo ssl_info;
- ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
- EXPECT_TRUE(ssl_info.is_valid());
- EXPECT_EQ(details.is_fatal_cert_error, ssl_info.is_fatal_cert_error);
- EXPECT_TRUE(ssl_info.cert->EqualsIncludingChain(
- details.cert_verify_result.verified_cert.get()));
- EXPECT_EQ(details.cert_verify_result.cert_status, ssl_info.cert_status);
- EXPECT_EQ(details.cert_verify_result.is_issued_by_known_root,
- ssl_info.is_issued_by_known_root);
- EXPECT_EQ(details.cert_verify_result.policy_compliance,
- ssl_info.ct_policy_compliance);
- }
- TEST_P(QuicChromiumClientSessionTest, IsFatalErrorNotSetForNonFatalError) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- SSLInfo ssl_info;
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.cert_status = CERT_STATUS_DATE_INVALID;
- details.is_fatal_cert_error = false;
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
- EXPECT_FALSE(ssl_info.is_fatal_cert_error);
- }
- TEST_P(QuicChromiumClientSessionTest, IsFatalErrorSetForFatalError) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- SSLInfo ssl_info;
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.cert_status = CERT_STATUS_DATE_INVALID;
- details.is_fatal_cert_error = true;
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
- EXPECT_TRUE(ssl_info.is_fatal_cert_error);
- }
- TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- }
- TEST_P(QuicChromiumClientSessionTest, Handle) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- NetLogWithSource session_net_log = session_->net_log();
- EXPECT_EQ(NetLogSourceType::QUIC_SESSION, session_net_log.source().type);
- EXPECT_EQ(NetLog::Get(), session_net_log.net_log());
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- EXPECT_TRUE(handle->IsConnected());
- EXPECT_FALSE(handle->OneRttKeysAvailable());
- EXPECT_EQ(version_, handle->GetQuicVersion());
- EXPECT_EQ(session_key_.server_id(), handle->server_id());
- EXPECT_EQ(session_net_log.source().type, handle->net_log().source().type);
- EXPECT_EQ(session_net_log.source().id, handle->net_log().source().id);
- EXPECT_EQ(session_net_log.net_log(), handle->net_log().net_log());
- IPEndPoint address;
- EXPECT_EQ(OK, handle->GetPeerAddress(&address));
- EXPECT_EQ(kIpEndPoint, address);
- EXPECT_TRUE(handle->CreatePacketBundler().get() != nullptr);
- CompleteCryptoHandshake();
- EXPECT_TRUE(handle->OneRttKeysAvailable());
- // Request a stream and verify that a stream was created.
- TestCompletionCallback callback;
- ASSERT_EQ(OK, handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- // Veirfy that the handle works correctly after the session is closed.
- EXPECT_FALSE(handle->IsConnected());
- EXPECT_TRUE(handle->OneRttKeysAvailable());
- EXPECT_EQ(version_, handle->GetQuicVersion());
- EXPECT_EQ(session_key_.server_id(), handle->server_id());
- EXPECT_EQ(session_net_log.source().type, handle->net_log().source().type);
- EXPECT_EQ(session_net_log.source().id, handle->net_log().source().id);
- EXPECT_EQ(session_net_log.net_log(), handle->net_log().net_log());
- EXPECT_EQ(ERR_CONNECTION_CLOSED, handle->GetPeerAddress(&address));
- EXPECT_TRUE(handle->CreatePacketBundler().get() == nullptr);
- {
- // Verify that CreateHandle() works even after the session is closed.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle2 =
- session_->CreateHandle(destination_);
- EXPECT_FALSE(handle2->IsConnected());
- EXPECT_TRUE(handle2->OneRttKeysAvailable());
- ASSERT_EQ(ERR_CONNECTION_CLOSED,
- handle2->RequestStream(/*requires_confirmation=*/false,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- }
- session_.reset();
- // Verify that the handle works correctly after the session is deleted.
- EXPECT_FALSE(handle->IsConnected());
- EXPECT_TRUE(handle->OneRttKeysAvailable());
- EXPECT_EQ(version_, handle->GetQuicVersion());
- EXPECT_EQ(session_key_.server_id(), handle->server_id());
- EXPECT_EQ(session_net_log.source().type, handle->net_log().source().type);
- EXPECT_EQ(session_net_log.source().id, handle->net_log().source().id);
- EXPECT_EQ(session_net_log.net_log(), handle->net_log().net_log());
- EXPECT_EQ(ERR_CONNECTION_CLOSED, handle->GetPeerAddress(&address));
- EXPECT_TRUE(handle->CreatePacketBundler().get() == nullptr);
- ASSERT_EQ(
- ERR_CONNECTION_CLOSED,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- }
- TEST_P(QuicChromiumClientSessionTest, StreamRequest) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Request a stream and verify that a stream was created.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(OK, handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, ConfirmationRequiredStreamRequest) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Request a stream and verify that a stream was created.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(OK, handle->RequestStream(/*requires_confirmation=*/true,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, StreamRequestBeforeConfirmation) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- // Request a stream and verify that a stream was created.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/true, callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- CompleteCryptoHandshake();
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, CancelStreamRequestBeforeRelease) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeRstPacket(packet_num++, true,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Request a stream and cancel it without releasing the stream.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(OK, handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- handle.reset();
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, AsyncStreamRequest) {
- MockQuicData quic_data(version_);
- uint64_t packet_num = 1;
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- // The open stream limit is set to 50 by
- // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
- // requested, a STREAMS_BLOCKED will be sent, indicating that it's blocked
- // at the limit of 50.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- packet_num++, true, 50,
- /*unidirectional=*/false));
- // Similarly, requesting the 52nd stream will also send a STREAMS_BLOCKED.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- packet_num++, true, 50,
- /*unidirectional=*/false));
- quic_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED,
- /*include_stop_sending_if_v99=*/false));
- quic_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(1),
- quic::QUIC_STREAM_CANCELLED,
- /*include_stop_sending_if_v99=*/false));
- // After the STREAMS_BLOCKED is sent, receive a MAX_STREAMS to increase
- // the limit to 100.
- quic_data.AddRead(
- ASYNC, server_maker_.MakeMaxStreamsPacket(1, true, 100,
- /*unidirectional=*/false));
- } else {
- quic_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- quic_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(1),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Open the maximum number of streams so that subsequent requests cannot
- // proceed immediately.
- EXPECT_EQ(GetMaxAllowedOutgoingBidirectionalStreams(), 50u);
- for (size_t i = 0; i < 50; i++) {
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- }
- EXPECT_EQ(session_->GetNumActiveStreams(), 50u);
- // Request a stream and verify that it's pending.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- // Request a second stream and verify that it's also pending.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle2 =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback2;
- ASSERT_EQ(ERR_IO_PENDING,
- handle2->RequestStream(/*requires_confirmation=*/false,
- callback2.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Close two stream to open up sending credits.
- quic::QuicRstStreamFrame rst(quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 0);
- session_->OnRstStream(rst);
- quic::QuicRstStreamFrame rst2(quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(1),
- quic::QUIC_STREAM_CANCELLED, 0);
- session_->OnRstStream(rst2);
- if (version_.HasIetfQuicFrames()) {
- // In IETF QUIC, to close the streams completely, we need to also receive
- // STOP_SENDING frames.
- quic::QuicStopSendingFrame stop_sending(
- quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED);
- session_->OnStopSendingFrame(stop_sending);
- quic::QuicStopSendingFrame stop_sending2(
- quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(1),
- quic::QUIC_STREAM_CANCELLED);
- session_->OnStopSendingFrame(stop_sending2);
- }
- if (!version_.HasIetfQuicFrames()) {
- // In Google QUIC, closing the streams is enough to unblock opening the next
- // ones.
- EXPECT_TRUE(callback.have_result());
- EXPECT_TRUE(callback2.have_result());
- } else {
- // In IETF QUIC, we need to receive a MAX_STREAMS frame to unblock opening
- // the next streams, and that hasn't been received yet.
- EXPECT_FALSE(callback.have_result());
- EXPECT_FALSE(callback2.have_result());
- }
- // Pump the message loop to read the packet containing the MAX_STREAMS frame.
- base::RunLoop().RunUntilIdle();
- // Make sure that both requests were unblocked.
- ASSERT_TRUE(callback.have_result());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- ASSERT_TRUE(callback2.have_result());
- EXPECT_THAT(callback2.WaitForResult(), IsOk());
- EXPECT_TRUE(handle2->ReleaseStream() != nullptr);
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- // Regression test for https://crbug.com/1021938.
- // When the connection is closed, there may be tasks queued in the message loop
- // to read the last packet, reading that packet should not crash.
- TEST_P(QuicChromiumClientSessionTest, ReadAfterConnectionClose) {
- MockQuicData quic_data(version_);
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- // The open stream limit is set to 50 by
- // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
- // requested, a STREAMS_BLOCKED will be sent, indicating that it's blocked
- // at the limit of 50.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 2, true, 50,
- /*unidirectional=*/false));
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 3, true, 50,
- /*unidirectional=*/false));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- // This packet will be read after connection is closed.
- quic_data.AddRead(
- ASYNC,
- server_maker_.MakeConnectionClosePacket(
- 1, false, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Open the maximum number of streams so that a subsequent request
- // can not proceed immediately.
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- }
- EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams());
- // Request two streams which will both be pending.
- // In V99 each will generate a max stream id for each attempt.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- std::unique_ptr<QuicChromiumClientSession::Handle> handle2 =
- session_->CreateHandle(destination_);
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(
- /*requires_confirmation=*/false,
- base::BindOnce(&QuicChromiumClientSessionTest::ResetHandleOnError,
- base::Unretained(this), &handle2),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- TestCompletionCallback callback2;
- ASSERT_EQ(ERR_IO_PENDING,
- handle2->RequestStream(/*requires_confirmation=*/false,
- callback2.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- session_->connection()->CloseConnection(
- quic::QUIC_NETWORK_IDLE_TIMEOUT, "Timed out",
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- // Pump the message loop to read the connection close packet.
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(handle2.get());
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, ClosedWithAsyncStreamRequest) {
- MockQuicData quic_data(version_);
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- // The open stream limit is set to 50 by
- // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
- // requested, a STREAMS_BLOCKED will be sent, indicating that it's blocked
- // at the limit of 50.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 2, true, 50,
- /*unidirectional=*/false));
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 3, true, 50,
- /*unidirectional=*/false));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Open the maximum number of streams so that a subsequent request
- // can not proceed immediately.
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- }
- EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams());
- // Request two streams which will both be pending.
- // In V99 each will generate a max stream id for each attempt.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- std::unique_ptr<QuicChromiumClientSession::Handle> handle2 =
- session_->CreateHandle(destination_);
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(
- /*requires_confirmation=*/false,
- base::BindOnce(&QuicChromiumClientSessionTest::ResetHandleOnError,
- base::Unretained(this), &handle2),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- TestCompletionCallback callback2;
- ASSERT_EQ(ERR_IO_PENDING,
- handle2->RequestStream(/*requires_confirmation=*/false,
- callback2.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- session_->connection()->CloseConnection(
- quic::QUIC_NETWORK_IDLE_TIMEOUT, "Timed out",
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- // Pump the message loop to read the connection close packet.
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(handle2.get());
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) {
- MockQuicData quic_data(version_);
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- // The open stream limit is set to 50 by
- // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
- // requested, a STREAMS_BLOCKED will be sent.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 2, true, 50,
- /*unidirectional=*/false));
- // This node receives the RST_STREAM+STOP_SENDING, it responds
- // with only a RST_STREAM.
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 3, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED,
- /*include_stop_sending_if_v99=*/false));
- } else {
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 1, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Open the maximum number of streams so that a subsequent request
- // can not proceed immediately.
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- }
- EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams());
- // Request a stream and verify that it's pending.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- // Cancel the pending stream request.
- handle.reset();
- // Close a stream and ensure that no new stream is created.
- quic::QuicRstStreamFrame rst(quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 0);
- session_->OnRstStream(rst);
- if (version_.HasIetfQuicFrames()) {
- // For version99, we require a STOP_SENDING as well as a RESET_STREAM to
- // fully close the stream.
- quic::QuicStopSendingFrame stop_sending(
- quic::kInvalidControlFrameId,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED);
- session_->OnStopSendingFrame(stop_sending);
- }
- EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumActiveStreams());
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeStreamRequest) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, true));
- quic_data.AddRead(
- ASYNC,
- server_maker_.MakeConnectionClosePacket(
- 1, false, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Send a ping so that client has outgoing traffic before receiving packets.
- session_->connection()->SendPing();
- // Pump the message loop to read the connection close packet.
- base::RunLoop().RunUntilIdle();
- // Request a stream and verify that it failed.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_CONNECTION_CLOSED,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeHandshakeConfirmed) {
- if (version_.UsesTls()) {
- // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
- // enabled and fix it.
- return;
- }
- // Force the connection close packet to use long headers with connection ID.
- server_maker_.SetEncryptionLevel(quic::ENCRYPTION_INITIAL);
- MockQuicData quic_data(version_);
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(
- ASYNC,
- server_maker_.MakeConnectionClosePacket(
- 1, false, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- // Request a stream and verify that it's pending.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/true, callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Close the connection and verify that the StreamRequest completes with
- // an error.
- quic_data.Resume();
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, ConnectionCloseWithPendingStreamRequest) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, true));
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- packet_num++, true, 50,
- /*unidirectional=*/false));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(
- ASYNC,
- server_maker_.MakeConnectionClosePacket(
- 1, false, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Send a ping so that client has outgoing traffic before receiving packets.
- session_->connection()->SendPing();
- // Open the maximum number of streams so that a subsequent request
- // can not proceed immediately.
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- }
- EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams());
- // Request a stream and verify that it's pending.
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- // Close the connection and verify that the StreamRequest completes with
- // an error.
- quic_data.Resume();
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
- MockQuicData quic_data(version_);
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- // Initial configuration is 50 dynamic streams. Taking into account
- // the static stream (headers), expect to block on when hitting the limit
- // of 50 streams
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 2, true, 50,
- /*unidirectional=*/false));
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 3, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- // For the second CreateOutgoingStream that fails because of hitting the
- // stream count limit.
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 4, true, 50,
- /*unidirectional=*/false));
- quic_data.AddRead(
- ASYNC, server_maker_.MakeMaxStreamsPacket(1, true, 50 + 2,
- /*unidirectional=*/false));
- } else {
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 1, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- std::vector<QuicChromiumClientStream*> streams;
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- streams.push_back(stream);
- }
- // This stream, the 51st dynamic stream, can not be opened.
- EXPECT_FALSE(
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()));
- EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams());
- // Close a stream and ensure I can now open a new one.
- quic::QuicStreamId stream_id = streams[0]->id();
- session_->ResetStream(stream_id, quic::QUIC_RST_ACKNOWLEDGEMENT);
- // Pump data, bringing in the max-stream-id
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()));
- quic::QuicRstStreamFrame rst1(quic::kInvalidControlFrameId, stream_id,
- quic::QUIC_STREAM_NO_ERROR, 0);
- session_->OnRstStream(rst1);
- EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumActiveStreams());
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()));
- }
- TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutNoResponse) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- } else if (GetParam().client_headers_include_h2_stream_dependency) {
- quic_data.AddWrite(
- ASYNC, client_maker_.MakePriorityPacket(packet_num++, true, 2, 0, 3));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_PUSH_STREAM_TIMED_OUT));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- spdy::Http2HeaderBlock promise_headers;
- promise_headers[":method"] = "GET";
- promise_headers[":authority"] = "www.example.org";
- promise_headers[":scheme"] = "https";
- promise_headers[":path"] = "/pushed.jpg";
- // Receive a PUSH PROMISE from the server.
- EXPECT_TRUE(session_->HandlePromised(
- stream->id(), GetNthServerInitiatedUnidirectionalStreamId(0),
- promise_headers));
- quic::QuicClientPromisedInfo* promised =
- session_->GetPromisedById(GetNthServerInitiatedUnidirectionalStreamId(0));
- EXPECT_TRUE(promised);
- // Fire alarm to time out the push stream.
- alarm_factory_.FireAlarm(
- quic::test::QuicClientPromisedInfoPeer::GetAlarm(promised));
- EXPECT_FALSE(
- session_->GetPromisedByUrl("https://www.example.org/pushed.jpg"));
- EXPECT_EQ(0u,
- QuicChromiumClientSessionPeer::GetPushedBytesCount(session_.get()));
- EXPECT_EQ(0u, QuicChromiumClientSessionPeer::GetPushedAndUnclaimedBytesCount(
- session_.get()));
- }
- TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutWithResponse) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- } else if (GetParam().client_headers_include_h2_stream_dependency) {
- quic_data.AddWrite(
- ASYNC, client_maker_.MakePriorityPacket(packet_num++, true, 2, 0, 3));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_PUSH_STREAM_TIMED_OUT));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- spdy::Http2HeaderBlock promise_headers;
- promise_headers[":method"] = "GET";
- promise_headers[":authority"] = "www.example.org";
- promise_headers[":scheme"] = "https";
- promise_headers[":path"] = "/pushed.jpg";
- session_->GetOrCreateStream(GetNthServerInitiatedUnidirectionalStreamId(0));
- // Receive a PUSH PROMISE from the server.
- EXPECT_TRUE(session_->HandlePromised(
- stream->id(), GetNthServerInitiatedUnidirectionalStreamId(0),
- promise_headers));
- session_->OnInitialHeadersComplete(
- GetNthServerInitiatedUnidirectionalStreamId(0), spdy::Http2HeaderBlock());
- // Read data on the pushed stream.
- quic::QuicStreamFrame data(GetNthServerInitiatedUnidirectionalStreamId(0),
- false, 0, absl::string_view("SP"));
- session_->OnStreamFrame(data);
- quic::QuicClientPromisedInfo* promised =
- session_->GetPromisedById(GetNthServerInitiatedUnidirectionalStreamId(0));
- EXPECT_TRUE(promised);
- // Fire alarm to time out the push stream.
- alarm_factory_.FireAlarm(
- quic::test::QuicClientPromisedInfoPeer::GetAlarm(promised));
- EXPECT_EQ(2u,
- QuicChromiumClientSessionPeer::GetPushedBytesCount(session_.get()));
- EXPECT_EQ(2u, QuicChromiumClientSessionPeer::GetPushedAndUnclaimedBytesCount(
- session_.get()));
- }
- // Regression test for crbug.com/968621.
- TEST_P(QuicChromiumClientSessionTest, PendingStreamOnRst) {
- if (!quic::VersionUsesHttp3(version_.transport_version))
- return;
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- quic::QuicStreamFrame data(GetNthServerInitiatedUnidirectionalStreamId(0),
- false, 1, absl::string_view("SP"));
- session_->OnStreamFrame(data);
- EXPECT_EQ(0u, session_->GetNumActiveStreams());
- quic::QuicRstStreamFrame rst(quic::kInvalidControlFrameId,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 0);
- session_->OnRstStream(rst);
- }
- // Regression test for crbug.com/971361.
- TEST_P(QuicChromiumClientSessionTest, ClosePendingStream) {
- if (!quic::VersionUsesHttp3(version_.transport_version))
- return;
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- quic::QuicStreamId id = GetNthServerInitiatedUnidirectionalStreamId(0);
- quic::QuicStreamFrame data(id, false, 1, absl::string_view("SP"));
- session_->OnStreamFrame(data);
- EXPECT_EQ(0u, session_->GetNumActiveStreams());
- session_->ResetStream(id, quic::QUIC_STREAM_NO_ERROR);
- }
- TEST_P(QuicChromiumClientSessionTest, CancelPushWhenPendingValidation) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- } else if (GetParam().client_headers_include_h2_stream_dependency) {
- quic_data.AddWrite(
- ASYNC, client_maker_.MakePriorityPacket(packet_num++, true, 2, 0, 3));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- spdy::Http2HeaderBlock promise_headers;
- promise_headers[":method"] = "GET";
- promise_headers[":authority"] = "www.example.org";
- promise_headers[":scheme"] = "https";
- promise_headers[":path"] = "/pushed.jpg";
- // Receive a PUSH PROMISE from the server.
- EXPECT_TRUE(session_->HandlePromised(
- stream->id(), GetNthServerInitiatedUnidirectionalStreamId(0),
- promise_headers));
- quic::QuicClientPromisedInfo* promised =
- session_->GetPromisedById(GetNthServerInitiatedUnidirectionalStreamId(0));
- EXPECT_TRUE(promised);
- // Initiate rendezvous.
- spdy::Http2HeaderBlock client_request = promise_headers.Clone();
- quic::test::TestPushPromiseDelegate delegate(/*match=*/true);
- promised->HandleClientRequest(client_request, &delegate);
- // Cancel the push before receiving the response to the pushed request.
- GURL pushed_url("https://www.example.org/pushed.jpg");
- test_push_delegate_.CancelPush(pushed_url);
- EXPECT_TRUE(session_->GetPromisedByUrl(pushed_url.spec()));
- // Reset the stream now before tear down.
- session_->ResetStream(GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT);
- }
- TEST_P(QuicChromiumClientSessionTest, CancelPushBeforeReceivingResponse) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- } else if (GetParam().client_headers_include_h2_stream_dependency) {
- quic_data.AddWrite(
- ASYNC, client_maker_.MakePriorityPacket(packet_num++, true, 2, 0, 3));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- spdy::Http2HeaderBlock promise_headers;
- promise_headers[":method"] = "GET";
- promise_headers[":authority"] = "www.example.org";
- promise_headers[":scheme"] = "https";
- promise_headers[":path"] = "/pushed.jpg";
- // Receive a PUSH PROMISE from the server.
- EXPECT_TRUE(session_->HandlePromised(
- stream->id(), GetNthServerInitiatedUnidirectionalStreamId(0),
- promise_headers));
- quic::QuicClientPromisedInfo* promised =
- session_->GetPromisedById(GetNthServerInitiatedUnidirectionalStreamId(0));
- EXPECT_TRUE(promised);
- // Cancel the push before receiving the response to the pushed request.
- GURL pushed_url("https://www.example.org/pushed.jpg");
- test_push_delegate_.CancelPush(pushed_url);
- EXPECT_FALSE(session_->GetPromisedByUrl(pushed_url.spec()));
- EXPECT_EQ(0u,
- QuicChromiumClientSessionPeer::GetPushedBytesCount(session_.get()));
- EXPECT_EQ(0u, QuicChromiumClientSessionPeer::GetPushedAndUnclaimedBytesCount(
- session_.get()));
- }
- TEST_P(QuicChromiumClientSessionTest, CancelPushAfterReceivingResponse) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- } else if (GetParam().client_headers_include_h2_stream_dependency) {
- quic_data.AddWrite(
- ASYNC, client_maker_.MakePriorityPacket(packet_num++, true, 2, 0, 3));
- }
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- spdy::Http2HeaderBlock promise_headers;
- promise_headers[":method"] = "GET";
- promise_headers[":authority"] = "www.example.org";
- promise_headers[":scheme"] = "https";
- promise_headers[":path"] = "/pushed.jpg";
- session_->GetOrCreateStream(GetNthServerInitiatedUnidirectionalStreamId(0));
- // Receive a PUSH PROMISE from the server.
- EXPECT_TRUE(session_->HandlePromised(
- stream->id(), GetNthServerInitiatedUnidirectionalStreamId(0),
- promise_headers));
- session_->OnInitialHeadersComplete(
- GetNthServerInitiatedUnidirectionalStreamId(0), spdy::Http2HeaderBlock());
- // Read data on the pushed stream.
- quic::QuicStreamFrame data(GetNthServerInitiatedUnidirectionalStreamId(0),
- false, 0, absl::string_view("SP"));
- session_->OnStreamFrame(data);
- quic::QuicClientPromisedInfo* promised =
- session_->GetPromisedById(GetNthServerInitiatedUnidirectionalStreamId(0));
- EXPECT_TRUE(promised);
- // Cancel the push after receiving data on the push stream.
- GURL pushed_url("https://www.example.org/pushed.jpg");
- test_push_delegate_.CancelPush(pushed_url);
- EXPECT_FALSE(session_->GetPromisedByUrl(pushed_url.spec()));
- EXPECT_EQ(2u,
- QuicChromiumClientSessionPeer::GetPushedBytesCount(session_.get()));
- EXPECT_EQ(2u, QuicChromiumClientSessionPeer::GetPushedAndUnclaimedBytesCount(
- session_.get()));
- }
- TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
- MockQuicData quic_data(version_);
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
- 2, true, 50,
- /*unidirectional=*/false));
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 3, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- quic_data.AddRead(
- ASYNC, server_maker_.MakeMaxStreamsPacket(1, true, 52,
- /*unidirectional=*/false));
- } else {
- quic_data.AddWrite(
- SYNCHRONOUS, client_maker_.MakeRstPacket(
- 1, true, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_RST_ACKNOWLEDGEMENT));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
- std::vector<QuicChromiumClientStream*> streams;
- for (size_t i = 0; i < kMaxOpenStreams; i++) {
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- EXPECT_TRUE(stream);
- streams.push_back(stream);
- }
- std::unique_ptr<QuicChromiumClientSession::Handle> handle =
- session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- ASSERT_EQ(
- ERR_IO_PENDING,
- handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
- // Close a stream and ensure I can now open a new one.
- quic::QuicStreamId stream_id = streams[0]->id();
- session_->ResetStream(stream_id, quic::QUIC_RST_ACKNOWLEDGEMENT);
- quic::QuicRstStreamFrame rst1(quic::kInvalidControlFrameId, stream_id,
- quic::QUIC_STREAM_NO_ERROR, 0);
- session_->OnRstStream(rst1);
- // Pump data, bringing in the max-stream-id
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(callback.have_result());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle->ReleaseStream() != nullptr);
- }
- TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // After receiving a GoAway, I should no longer be able to create outgoing
- // streams.
- if (VersionUsesHttp3(version_.transport_version)) {
- session_->OnHttp3GoAway(0);
- } else {
- session_->connection()->OnGoAwayFrame(
- quic::QuicGoAwayFrame(quic::kInvalidControlFrameId,
- quic::QUIC_PEER_GOING_AWAY, 1u, "Going away."));
- }
- EXPECT_EQ(nullptr, QuicChromiumClientSessionPeer::CreateOutgoingStream(
- session_.get()));
- }
- TEST_P(QuicChromiumClientSessionTest, CanPool) {
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- // Load a cert that is valid for:
- // www.example.org
- // mail.example.org
- // www.example.com
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- EXPECT_TRUE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_ENABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kDisable,
- /*require_dns_https_alpn=*/false)));
- #if BUILDFLAG(IS_ANDROID)
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- SocketTag tag2(getuid(), 0x87654321);
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, tag1,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, tag2,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- #endif
- EXPECT_TRUE(session_->CanPool(
- "mail.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_TRUE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "mail.google.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- const SchemefulSite kSiteFoo(GURL("http://foo.test/"));
- // Check that NetworkIsolationKey is respected when feature is enabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- features::kPartitionConnectionsByNetworkIsolationKey);
- EXPECT_TRUE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(kSiteFoo, kSiteFoo),
- SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kPartitionConnectionsByNetworkIsolationKey);
- EXPECT_FALSE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(kSiteFoo, kSiteFoo),
- SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- }
- TEST_P(QuicChromiumClientSessionTest, CanPoolExpectCT) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures(
- /* enabled_features */
- {TransportSecurityState::kDynamicExpectCTFeature,
- features::kPartitionExpectCTStateByNetworkIsolationKey,
- features::kPartitionConnectionsByNetworkIsolationKey},
- /* disabled_features */
- {});
- NetworkIsolationKey network_isolation_key =
- NetworkIsolationKey::CreateTransient();
- // Need to create a session key after setting
- // kPartitionExpectCTStateByNetworkIsolationKey, otherwise, it will ignore the
- // NetworkIsolationKey value.
- session_key_ =
- QuicSessionKey(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED,
- SocketTag(), network_isolation_key,
- SecureDnsPolicy::kAllow, /*require_dns_https_alpn=*/false);
- // Need to create this after enabling
- // kPartitionExpectCTStateByNetworkIsolationKey.
- transport_security_state_ = std::make_unique<TransportSecurityState>();
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- // Load a cert that is valid for:
- // www.example.org
- // mail.example.org
- // www.example.com
- // Details with a CT error.
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- details.cert_verify_result.is_issued_by_known_root = true;
- details.cert_verify_result.policy_compliance =
- ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- // Pooling succeeds if CT isn't required.
- EXPECT_TRUE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- network_isolation_key, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- // Adding Expect-CT data for different NetworkIsolationKeys should have no
- // effect.
- base::Time expiry = base::Time::Now() + base::Days(1);
- transport_security_state_->AddExpectCT(
- "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
- NetworkIsolationKey::CreateTransient());
- transport_security_state_->AddExpectCT(
- "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
- NetworkIsolationKey());
- EXPECT_TRUE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- network_isolation_key, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- // Adding Expect-CT data for the same NetworkIsolationKey should prevent
- // pooling.
- transport_security_state_->AddExpectCT(
- "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
- network_isolation_key);
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- network_isolation_key, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- // Much as above, but uses a non-empty NetworkIsolationKey.
- TEST_P(QuicChromiumClientSessionTest, CanPoolWithNetworkIsolationKey) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kPartitionConnectionsByNetworkIsolationKey);
- const SchemefulSite kSiteFoo(GURL("http://foo.test/"));
- const SchemefulSite kSiteBar(GURL("http://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSiteFoo, kSiteFoo);
- const NetworkIsolationKey kNetworkIsolationKey2(kSiteBar, kSiteBar);
- session_key_ =
- QuicSessionKey(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED,
- SocketTag(), kNetworkIsolationKey1,
- SecureDnsPolicy::kAllow, /*require_dns_https_alpn=*/false);
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- // Load a cert that is valid for:
- // www.example.org
- // mail.example.org
- // www.example.com
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- EXPECT_TRUE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_ENABLED, SocketTag(),
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- #if BUILDFLAG(IS_ANDROID)
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- SocketTag tag2(getuid(), 0x87654321);
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, tag1,
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "www.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, tag2,
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- #endif
- EXPECT_TRUE(session_->CanPool(
- "mail.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_TRUE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "mail.google.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- kNetworkIsolationKey1, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- kNetworkIsolationKey2, SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- EXPECT_FALSE(session_->CanPool(
- "mail.example.com",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- net::features::kStaticKeyPinningEnforcement);
- // Configure the TransportSecurityStateSource so that kPreloadedPKPHost will
- // have static PKP pins set.
- ScopedTransportSecurityStateSource scoped_security_state_source;
- // |net::test_default::kHSTSSource| defines pins for kPreloadedPKPHost.
- // (This hostname must be in the spdy_pooling.pem SAN.)
- const char kPreloadedPKPHost[] = "www.example.org";
- // A hostname without any static state. (This hostname isn't in
- // spdy_pooling.pem SAN, but that's okay because the
- // ProofVerifyDetailsChromium are faked.)
- const char kNoPinsHost[] = "no-pkp.example.org";
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- transport_security_state_->EnableStaticPinsForTesting();
- transport_security_state_->SetPinningListAlwaysTimelyForTesting(true);
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.is_issued_by_known_root = true;
- uint8_t bad_pin = 3;
- details.cert_verify_result.public_key_hashes.push_back(
- GetTestHashValue(bad_pin));
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientSessionPeer::SetHostname(session_.get(), kNoPinsHost);
- EXPECT_FALSE(session_->CanPool(
- kPreloadedPKPHost,
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
- ScopedTransportSecurityStateSource scoped_security_state_source;
- MockQuicData quic_data(version_);
- if (VersionUsesHttp3(version_.transport_version))
- quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- transport_security_state_->EnableStaticPinsForTesting();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- details.cert_verify_result.is_issued_by_known_root = true;
- HashValue primary_pin(HASH_VALUE_SHA256);
- EXPECT_TRUE(primary_pin.FromString(
- "sha256/Nn8jk5By4Vkq6BeOVZ7R7AC6XUUBZsWmUbJR1f1Y5FY="));
- details.cert_verify_result.public_key_hashes.push_back(primary_pin);
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
- EXPECT_TRUE(session_->CanPool(
- "mail.example.org",
- QuicSessionKey("foo", 1234, PRIVACY_MODE_DISABLED, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- /*require_dns_https_alpn=*/false)));
- }
- TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
- if (VersionUsesHttp3(version_.transport_version)) {
- SetIetfConnectionMigrationFlagsAndConnectionOptions();
- }
- quic::QuicConnectionId cid_on_new_path =
- quic::test::TestConnectionId(12345678);
- MockQuicData quic_data(version_);
- int packet_num = 1;
- int peer_packet_num = 1;
- socket_data_.reset();
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- quic_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
- peer_packet_num++, /*include_version=*/false,
- cid_on_new_path,
- /*sequence_number=*/1u,
- /*retire_prior_to=*/0u));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- if (VersionUsesHttp3(version_.transport_version)) {
- // Make new connection ID available after handshake completion.
- quic_data.Resume();
- base::RunLoop().RunUntilIdle();
- }
- char data[] = "ABCD";
- MockQuicData quic_data2(version_);
- if (VersionUsesHttp3(version_.transport_version)) {
- client_maker_.set_connection_id(cid_on_new_path);
- }
- quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- if (version_.UsesHttp3()) {
- quic_data2.AddWrite(SYNCHRONOUS,
- client_maker_.MakeAckAndPingPacket(
- packet_num++, /*include_version=*/false,
- /*largest_received=*/peer_packet_num - 1,
- /*smallest_received=*/1));
- } else {
- quic_data2.AddWrite(SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, true));
- }
- quic_data2.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeDataPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
- false, absl::string_view(data)));
- quic_data2.AddSocketDataToFactory(&socket_factory_);
- // Create connected socket.
- std::unique_ptr<DatagramClientSocket> new_socket =
- socket_factory_.CreateDatagramClientSocket(DatagramSocket::RANDOM_BIND,
- NetLog::Get(), NetLogSource());
- EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
- // Create reader and writer.
- auto new_reader = std::make_unique<QuicChromiumPacketReader>(
- new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
- quic::QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- net_log_with_source_);
- new_reader->StartReading();
- std::unique_ptr<QuicChromiumPacketWriter> new_writer(
- CreateQuicChromiumPacketWriter(new_socket.get(), session_.get()));
- IPEndPoint local_address;
- new_socket->GetLocalAddress(&local_address);
- IPEndPoint peer_address;
- new_socket->GetPeerAddress(&peer_address);
- // Migrate session.
- EXPECT_TRUE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- // Spin message loop to complete migration.
- base::RunLoop().RunUntilIdle();
- // Write data to session.
- QuicChromiumClientStream* stream =
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get());
- quic::test::QuicStreamPeer::SendBuffer(stream).SaveStreamData(data);
- quic::test::QuicStreamPeer::SetStreamBytesWritten(4, stream);
- session_->WritevData(stream->id(), 4, 0, quic::NO_FIN,
- quic::NOT_RETRANSMISSION,
- quic::ENCRYPTION_FORWARD_SECURE);
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
- if (VersionUsesHttp3(version_.transport_version)) {
- SetIetfConnectionMigrationFlagsAndConnectionOptions();
- }
- MockQuicData quic_data(version_);
- socket_data_.reset();
- int packet_num = 1;
- int peer_packet_num = 1;
- quic::QuicConnectionId next_cid =
- quic::QuicUtils::CreateReplacementConnectionId(
- quic::QuicUtils::CreateRandomConnectionId(&random_));
- uint64_t next_cid_sequence_number = 1u;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddRead(
- ASYNC, server_maker_.MakeNewConnectionIdPacket(
- peer_packet_num++, /*include_version=*/false, next_cid,
- next_cid_sequence_number,
- /*retire_prior_to=*/next_cid_sequence_number - 1));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- }
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- if (VersionUsesHttp3(version_.transport_version)) {
- // Make connection ID available for the first migration.
- quic_data.Resume();
- }
- /* Migration succeeds when maximum number of readers is not reached.*/
- for (size_t i = 0; i < kMaxReadersPerQuicSession - 1; ++i) {
- MockQuicData quic_data2(version_);
- if (!VersionUsesHttp3(version_.transport_version)) {
- quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- quic_data2.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
- } else {
- client_maker_.set_connection_id(next_cid);
- quic_data2.AddWrite(SYNCHRONOUS,
- client_maker_.MakeAckAndPingPacket(
- packet_num++, /*include_version=*/true,
- /*largest_received=*/peer_packet_num - 1,
- /*smallest_received=*/1));
- quic_data2.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data2.AddWrite(
- ASYNC, client_maker_.MakeRetireConnectionIdPacket(
- packet_num++, /*include_version=*/false,
- /*sequence_number=*/next_cid_sequence_number - 1));
- next_cid = quic::QuicUtils::CreateReplacementConnectionId(next_cid);
- ++next_cid_sequence_number;
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeNewConnectionIdPacket(
- peer_packet_num++, /*include_version=*/false, next_cid,
- next_cid_sequence_number,
- /*retire_prior_to=*/next_cid_sequence_number - 1));
- quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- }
- quic_data2.AddSocketDataToFactory(&socket_factory_);
- // Create connected socket.
- std::unique_ptr<DatagramClientSocket> new_socket =
- socket_factory_.CreateDatagramClientSocket(
- DatagramSocket::RANDOM_BIND, NetLog::Get(), NetLogSource());
- EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
- // Create reader and writer.
- auto new_reader = std::make_unique<QuicChromiumPacketReader>(
- new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
- quic::QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- net_log_with_source_);
- new_reader->StartReading();
- std::unique_ptr<QuicChromiumPacketWriter> new_writer(
- CreateQuicChromiumPacketWriter(new_socket.get(), session_.get()));
- IPEndPoint local_address;
- new_socket->GetLocalAddress(&local_address);
- IPEndPoint peer_address;
- new_socket->GetPeerAddress(&peer_address);
- // Migrate session.
- EXPECT_TRUE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- // Spin message loop to complete migration.
- base::RunLoop().RunUntilIdle();
- if (VersionUsesHttp3(version_.transport_version)) {
- alarm_factory_.FireAlarm(
- quic::test::QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(
- session_->connection()));
- // Make new connection ID available for subsequent migration.
- quic_data2.Resume();
- base::RunLoop().RunUntilIdle();
- }
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
- }
- /* Migration fails when maximum number of readers is reached.*/
- MockQuicData quic_data2(version_);
- quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- quic_data2.AddSocketDataToFactory(&socket_factory_);
- // Create connected socket.
- std::unique_ptr<DatagramClientSocket> new_socket =
- socket_factory_.CreateDatagramClientSocket(DatagramSocket::RANDOM_BIND,
- NetLog::Get(), NetLogSource());
- EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
- // Create reader and writer.
- auto new_reader = std::make_unique<QuicChromiumPacketReader>(
- new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
- quic::QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- net_log_with_source_);
- new_reader->StartReading();
- std::unique_ptr<QuicChromiumPacketWriter> new_writer(
- CreateQuicChromiumPacketWriter(new_socket.get(), session_.get()));
- IPEndPoint local_address;
- new_socket->GetLocalAddress(&local_address);
- IPEndPoint peer_address;
- new_socket->GetPeerAddress(&peer_address);
- EXPECT_FALSE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
- if (VersionUsesHttp3(version_.transport_version)) {
- SetIetfConnectionMigrationFlagsAndConnectionOptions();
- }
- MockQuicData quic_data(version_);
- socket_data_.reset();
- int packet_num = 1;
- int peer_packet_num = 1;
- quic::QuicConnectionId cid_on_new_path =
- quic::test::TestConnectionId(12345678);
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- quic_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
- peer_packet_num++, /*include_version=*/false,
- cid_on_new_path,
- /*sequence_number=*/1u,
- /*retire_prior_to=*/0u));
- } else {
- quic_data.AddWrite(ASYNC, client_maker_.MakePingPacket(packet_num++, true));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_NETWORK_CHANGED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- if (!VersionUsesHttp3(version_.transport_version)) {
- session_->connection()->SendPing();
- } else {
- // Make new connection ID available after handshake completion.
- quic_data.Resume();
- base::RunLoop().RunUntilIdle();
- }
- MockQuicData quic_data2(version_);
- if (VersionUsesHttp3(version_.transport_version)) {
- client_maker_.set_connection_id(cid_on_new_path);
- }
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data2.AddWrite(SYNCHRONOUS,
- client_maker_.MakeAckAndPingPacket(
- packet_num++,
- /*include_version=*/false,
- /*largest_received=*/peer_packet_num - 1,
- /*smallest_received=*/1));
- } else {
- quic_data2.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
- }
- quic_data2.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data2.AddRead(
- ASYNC, server_maker_.MakePingPacket(1, /*include_version=*/false));
- quic_data2.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data2.AddRead(ASYNC, ERR_NETWORK_CHANGED);
- quic_data2.AddSocketDataToFactory(&socket_factory_);
- // Create connected socket.
- std::unique_ptr<DatagramClientSocket> new_socket =
- socket_factory_.CreateDatagramClientSocket(DatagramSocket::RANDOM_BIND,
- NetLog::Get(), NetLogSource());
- EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
- // Create reader and writer.
- auto new_reader = std::make_unique<QuicChromiumPacketReader>(
- new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
- quic::QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- net_log_with_source_);
- new_reader->StartReading();
- std::unique_ptr<QuicChromiumPacketWriter> new_writer(
- CreateQuicChromiumPacketWriter(new_socket.get(), session_.get()));
- IPEndPoint local_address;
- new_socket->GetLocalAddress(&local_address);
- IPEndPoint peer_address;
- new_socket->GetPeerAddress(&peer_address);
- // Store old socket and migrate session.
- EXPECT_TRUE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- // Spin message loop to complete migration.
- base::RunLoop().RunUntilIdle();
- if (VersionUsesHttp3(version_.transport_version)) {
- EXPECT_TRUE(
- quic::test::QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(
- session_->connection())
- ->IsSet());
- }
- // Read error on old socket does not impact session.
- quic_data.Resume();
- EXPECT_TRUE(session_->connection()->connected());
- quic_data2.Resume();
- // Read error on new socket causes session close.
- EXPECT_TRUE(session_->connection()->connected());
- quic_data2.Resume();
- EXPECT_FALSE(session_->connection()->connected());
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
- }
- TEST_P(QuicChromiumClientSessionTest, RetransmittableOnWireTimeout) {
- migrate_session_early_v2_ = true;
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, true));
- quic_data.AddRead(ASYNC, server_maker_.MakeAckPacket(1, packet_num - 1, 1));
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, false));
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Open a stream since the connection only sends PINGs to keep a
- // retransmittable packet on the wire if there's an open stream.
- EXPECT_TRUE(
- QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()));
- quic::QuicAlarm* alarm =
- quic::test::QuicConnectionPeer::GetPingAlarm(session_->connection());
- EXPECT_FALSE(alarm->IsSet());
- // Send PING, which will be ACKed by the server. After the ACK, there will be
- // no retransmittable packets on the wire, so the alarm should be set.
- session_->connection()->SendPing();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(alarm->IsSet());
- EXPECT_EQ(
- clock_.ApproximateNow() + quic::QuicTime::Delta::FromMilliseconds(200),
- alarm->deadline());
- // Advance clock and simulate the alarm firing. This should cause a PING to be
- // sent.
- clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(200));
- alarm_factory_.FireAlarm(alarm);
- base::RunLoop().RunUntilIdle();
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- // Regression test for https://crbug.com/1043531.
- TEST_P(QuicChromiumClientSessionTest, ResetOnEmptyResponseHeaders) {
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(ASYNC,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_GENERAL_PROTOCOL_ERROR));
- } else {
- // In case of Google QUIC, QuicSpdyStream resets the stream.
- quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
- packet_num++, true,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_HEADERS_TOO_LARGE));
- }
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ProofVerifyDetailsChromium details;
- details.cert_verify_result.verified_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
- ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
- CompleteCryptoHandshake();
- session_->OnProofVerifyDetailsAvailable(details);
- auto session_handle = session_->CreateHandle(destination_);
- TestCompletionCallback callback;
- EXPECT_EQ(OK, session_handle->RequestStream(/*requires_confirmation=*/false,
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS));
- auto stream_handle = session_handle->ReleaseStream();
- EXPECT_TRUE(stream_handle->IsOpen());
- auto* stream = quic::test::QuicSessionPeer::GetOrCreateStream(
- session_.get(), stream_handle->id());
- const quic::QuicHeaderList empty_response_headers;
- static_cast<quic::QuicSpdyStream*>(stream)->OnStreamHeaderList(
- /* fin = */ false, /* frame_len = */ 0, empty_response_headers);
- if (VersionUsesHttp3(version_.transport_version)) {
- // In case of IETF QUIC, QuicSpdyStream::OnStreamHeaderList() calls
- // QuicChromiumClientStream::OnInitialHeadersComplete() with the empty
- // header list, and QuicChromiumClientStream signals an error.
- spdy::Http2HeaderBlock header_block;
- int rv = stream_handle->ReadInitialHeaders(&header_block,
- CompletionOnceCallback());
- EXPECT_THAT(rv, IsError(net::ERR_QUIC_PROTOCOL_ERROR));
- }
- base::RunLoop().RunUntilIdle();
- quic_data.Resume();
- EXPECT_TRUE(quic_data.AllReadDataConsumed());
- EXPECT_TRUE(quic_data.AllWriteDataConsumed());
- }
- // This test verifies that when handles::NetworkHandle is not supported and
- // there is no network change, session reports to the connectivity monitor
- // correctly on path degrading detection and recovery.
- TEST_P(QuicChromiumClientSessionTest,
- DegradingWithoutNetworkChange_NoNetworkHandle) {
- // Add a connectivity monitor for testing.
- default_network_ = handles::kInvalidNetworkHandle;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- Initialize();
- // Fire path degrading detection.
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- // Fire again.
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // Close the session but keep the session around, the connectivity monitor
- // will not remove the tracking immediately.
- session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // Delete the session will remove the degrading count in connectivity
- // monitor.
- session_.reset();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- }
- // This test verifies that when the handles::NetworkHandle is not supported, and
- // there are speculated network change reported via OnIPAddressChange, session
- // still reports to the connectivity monitor correctly on path degrading
- // detection and recovery.
- TEST_P(QuicChromiumClientSessionTest, DegradingWithIPAddressChange) {
- // Default network is always set to handles::kInvalidNetworkHandle.
- default_network_ = handles::kInvalidNetworkHandle;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- Initialize();
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // When handles::NetworkHandle is not supported, network change is notified
- // via IP address change.
- connectivity_monitor_->OnIPAddressChanged();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- // When handles::NetworkHandle is not supported and IP address changes,
- // session either goes away or gets closed. When it goes away,
- // reporting to connectivity monitor is disabled.
- connectivity_monitor_->OnSessionGoingAwayOnIPAddressChange(session_.get());
- // Even if session detects recovery or degradation, this session is no longer
- // on the default network and connectivity monitor will not update.
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_.reset();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- }
- // This test verifies that when handles::NetworkHandle is supported but
- // migration is not supported and there's no network change, session reports to
- // connectivity monitor correctly on path degrading detection or recovery.
- // Default network change is currently reported with valid
- // handles::NetworkHandles while session's current network interface is tracked
- // by |default_network_|.
- TEST_P(QuicChromiumClientSessionTest,
- DegradingOnDeafultNetwork_WithoutMigration) {
- default_network_ = kDefaultNetworkForTests;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- Initialize();
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // Close the session but keep the session around, the connectivity monitor
- // should not remove the count immediately.
- session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // Delete the session will remove the degrading count in connectivity
- // monitor.
- session_.reset();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- }
- // This test verifies that when handles::NetworkHandle is supported but
- // migrations is not supported and there is network changes, session reports to
- // the connectivity monitor correctly on path degrading detection or recovery.
- TEST_P(QuicChromiumClientSessionTest,
- DegradingWithDeafultNetworkChange_WithoutMigration) {
- default_network_ = kDefaultNetworkForTests;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- Initialize();
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- // Simulate the default network change.
- connectivity_monitor_->OnDefaultNetworkUpdated(kNewNetworkForTests);
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnNetworkMadeDefault(kNewNetworkForTests);
- // Session stays on the old default network, and recovers.
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- // Session degrades again on the old default.
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- // Simulate that default network switches back to the old default.
- connectivity_monitor_->OnDefaultNetworkUpdated(kDefaultNetworkForTests);
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- session_->OnNetworkMadeDefault(kDefaultNetworkForTests);
- // Session recovers again on the (old) default.
- session_->OnForwardProgressMadeAfterPathDegrading();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- // Session degrades again on the (old) default.
- session_->ReallyOnPathDegrading();
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
- quic::ConnectionCloseBehavior::SILENT_CLOSE);
- EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
- session_.reset();
- EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
- }
- TEST_P(QuicChromiumClientSessionTest, WriteErrorDuringCryptoConnect) {
- // Add a connectivity monitor for testing.
- default_network_ = kDefaultNetworkForTests;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- // Use unmocked crypto stream to do crypto connect.
- crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
- MockQuicData quic_data(version_);
- // Trigger a packet write error when sending packets in crypto connect.
- quic_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- ASSERT_THAT(session_->CryptoConnect(callback_.callback()),
- IsError(ERR_QUIC_HANDSHAKE_FAILED));
- // Verify error count is properly recorded.
- EXPECT_EQ(1u, connectivity_monitor_->GetCountForWriteErrorCode(
- ERR_ADDRESS_UNREACHABLE));
- EXPECT_EQ(0u, connectivity_monitor_->GetCountForWriteErrorCode(
- ERR_CONNECTION_RESET));
- // Simulate a default network change, write error stats should be reset.
- connectivity_monitor_->OnDefaultNetworkUpdated(kNewNetworkForTests);
- EXPECT_EQ(0u, connectivity_monitor_->GetCountForWriteErrorCode(
- ERR_ADDRESS_UNREACHABLE));
- }
- TEST_P(QuicChromiumClientSessionTest, WriteErrorAfterHandshakeConfirmed) {
- // Add a connectivity monitor for testing.
- default_network_ = handles::kInvalidNetworkHandle;
- connectivity_monitor_ =
- std::make_unique<QuicConnectivityMonitor>(default_network_);
- MockQuicData quic_data(version_);
- int packet_num = 1;
- if (version_.HasIetfQuicFrames()) {
- quic_data.AddWrite(SYNCHRONOUS,
- client_maker_.MakeInitialSettingsPacket(packet_num++));
- }
- // When sending the PING packet, trigger a packet write error.
- quic_data.AddWrite(SYNCHRONOUS, ERR_CONNECTION_RESET);
- quic_data.AddRead(ASYNC, ERR_IO_PENDING);
- quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
- quic_data.AddSocketDataToFactory(&socket_factory_);
- Initialize();
- CompleteCryptoHandshake();
- // Send a ping so that client has outgoing traffic before receiving packets.
- session_->connection()->SendPing();
- // Verify error count is properly recorded.
- EXPECT_EQ(1u, connectivity_monitor_->GetCountForWriteErrorCode(
- ERR_CONNECTION_RESET));
- EXPECT_EQ(0u, connectivity_monitor_->GetCountForWriteErrorCode(
- ERR_ADDRESS_UNREACHABLE));
- connectivity_monitor_->OnIPAddressChanged();
- // If network handle is supported, IP Address change is a no-op. Otherwise it
- // clears all stats.
- size_t expected_error_count =
- NetworkChangeNotifier::AreNetworkHandlesSupported() ? 1u : 0u;
- EXPECT_EQ(
- expected_error_count,
- connectivity_monitor_->GetCountForWriteErrorCode(ERR_CONNECTION_RESET));
- }
- } // namespace
- } // namespace net::test
|