src/net/quic/quic_network_transaction_unittest.cc
// Much like above test, but verifies that NetworkIsolationKey is respected.
Much like above test, but verifies that NetworkIsolationKey is respected.
Much like above test but verifies that NetworkIsolationKey is respected .
TEST_P(QuicNetworkTransactionTest,
       ProtocolErrorAfterHandshakeConfirmedThenBrokenWithNetworkIsolationKey) {
  if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
    return;
  }
  const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
  const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
  const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
  const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures(
      {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
       features::kPartitionConnectionsByNetworkIsolationKey},
      {});
  http_server_properties_ = std::make_unique<HttpServerProperties>();
  context_.params()->idle_connection_timeout = base::TimeDelta::FromSeconds(5);
  MockQuicData quic_data(version_);
  uint64_t packet_number = 1;
  client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  if (VersionUsesHttp3(version_.transport_version)) {
    quic_data.AddWrite(SYNCHRONOUS,
                       ConstructInitialSettingsPacket(packet_number++));
  }
  quic_data.AddWrite(
      SYNCHRONOUS,
      ConstructClientRequestHeadersPacket(
          packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true,
          true, GetRequestHeaders("GET", "https", "/")));
  client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  
  quic_data.AddRead(
      ASYNC, ConstructServerRstPacket(
                 1, false, GetNthClientInitiatedBidirectionalStreamId(47),
                 quic::QUIC_STREAM_LAST_ERROR));
  std::string quic_error_details = "Data for nonexistent stream";
  quic_data.AddWrite(SYNCHRONOUS,
                     ConstructClientAckAndConnectionClosePacket(
                         packet_number++, 1, 1, 1, quic::QUIC_INVALID_STREAM_ID,
                         quic_error_details, quic::IETF_RST_STREAM));
  quic_data.AddSocketDataToFactory(&socket_factory_);
  MockWrite http_writes[] = {
      MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
      MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"),
      MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")};
  MockRead http_reads[] = {
      MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
      MockRead(SYNCHRONOUS, 4, kQuicAlternativeServiceHeader),
      MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)};
  SequencedSocketData http_data(http_reads, http_writes);
  socket_factory_.AddSocketDataProvider(&http_data);
  socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
  host_resolver_.set_synchronous_mode(true);
  host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
                                           "");
  CreateSession();
  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT,
                                  kNetworkIsolationKey1);
  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT,
                                  kNetworkIsolationKey2);
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
  TestCompletionCallback callback;
  request_.network_isolation_key = kNetworkIsolationKey1;
  int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  base::RunLoop().RunUntilIdle();
  crypto_client_stream_factory_.last_stream()
      ->NotifySessionOneRttKeyAvailable();
  quic_data.Resume();
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(quic_data.AllWriteDataConsumed());
  EXPECT_THAT(callback.WaitForResult(), IsOk());
  ASSERT_TRUE(quic_data.AllWriteDataConsumed());
  ASSERT_FALSE(http_data.AllReadDataConsumed());
  CheckResponseData(&trans, "hello world");
  ASSERT_TRUE(http_data.AllWriteDataConsumed());
  ASSERT_TRUE(http_data.AllReadDataConsumed());
  ExpectBrokenAlternateProtocolMapping(kNetworkIsolationKey1);
  ExpectQuicAlternateProtocolMapping(kNetworkIsolationKey2);
  AddHttpDataAndRunRequest();
  request_.network_isolation_key = kNetworkIsolationKey2;
  AddQuicDataAndRunRequest();
  ExpectBrokenAlternateProtocolMapping(kNetworkIsolationKey1);
  ExpectQuicAlternateProtocolMapping(kNetworkIsolationKey2);
}
TEST_P ( QuicNetworkTransactionTest , ProtocolErrorAfterHandshakeConfirmedThenBrokenWithNetworkIsolationKey ) { if ( version_ . handshake_protocol == quic :: PROTOCOL_TLS1_3 ) { return ; } const url :: Origin kOrigin1 = url :: Origin :: Create ( GURL ( " " ) ) ; const net :: NetworkIsolationKey kNetworkIsolationKey1 ( kOrigin1 , kOrigin1 ) ; const url :: Origin kOrigin2 = url :: Origin :: Create ( GURL ( " " ) ) ; const net :: NetworkIsolationKey kNetworkIsolationKey2 ( kOrigin2 , kOrigin2 ) ; base :: test :: ScopedFeatureList feature_list ; feature_list . InitWithFeatures ( { features :: kPartitionHttpServerPropertiesByNetworkIsolationKey , features :: kPartitionConnectionsByNetworkIsolationKey } , { } ) ; http_server_properties_ = std :: make_unique < HttpServerProperties > ( ) ; context_ . params ( ) -> idle_connection_timeout = base :: TimeDelta :: FromSeconds ( 5 ) ; MockQuicData quic_data ( version_ ) ; uint64_t packet_number = 1 ; client_maker_ -> SetEncryptionLevel ( quic :: ENCRYPTION_ZERO_RTT ) ; if ( VersionUsesHttp3 ( version_ . transport_version ) ) { quic_data . AddWrite ( SYNCHRONOUS , ConstructInitialSettingsPacket ( packet_number ++ ) ) ; } quic_data . AddWrite ( SYNCHRONOUS , ConstructClientRequestHeadersPacket ( packet_number ++ , GetNthClientInitiatedBidirectionalStreamId ( 0 ) , true , true , GetRequestHeaders ( " " , " " , " " ) ) ) ; client_maker_ -> SetEncryptionLevel ( quic :: ENCRYPTION_FORWARD_SECURE ) ; quic_data . AddRead ( ASYNC , ERR_IO_PENDING ) ; quic_data . AddRead ( ASYNC , ConstructServerRstPacket ( 1 , false , GetNthClientInitiatedBidirectionalStreamId ( 47 ) , quic :: QUIC_STREAM_LAST_ERROR ) ) ; std :: string quic_error_details = " " ; quic_data . AddWrite ( SYNCHRONOUS , ConstructClientAckAndConnectionClosePacket ( packet_number ++ , 1 , 1 , 1 , quic :: QUIC_INVALID_STREAM_ID , quic_error_details , quic :: IETF_RST_STREAM ) ) ; quic_data . AddSocketDataToFactory ( & socket_factory_ ) ; MockWrite http_writes [ ] = { MockWrite ( SYNCHRONOUS , 0 , " \r \n " ) , MockWrite ( SYNCHRONOUS , 1 , " \r \n " ) , MockWrite ( SYNCHRONOUS , 2 , " \r \n \r \n " ) } ; MockRead http_reads [ ] = { MockRead ( SYNCHRONOUS , 3 , " \r \n " ) , MockRead ( SYNCHRONOUS , 4 , kQuicAlternativeServiceHeader ) , MockRead ( SYNCHRONOUS , 5 , " " ) , MockRead ( SYNCHRONOUS , OK , 6 ) } ; SequencedSocketData http_data ( http_reads , http_writes ) ; socket_factory_ . AddSocketDataProvider ( & http_data ) ; socket_factory_ . AddSSLSocketDataProvider ( & ssl_data_ ) ; host_resolver_ . set_synchronous_mode ( true ) ; host_resolver_ . rules ( ) -> AddIPLiteralRule ( " " , " " , " " ) ; CreateSession ( ) ; AddQuicAlternateProtocolMapping ( MockCryptoClientStream :: ZERO_RTT , kNetworkIsolationKey1 ) ; AddQuicAlternateProtocolMapping ( MockCryptoClientStream :: ZERO_RTT , kNetworkIsolationKey2 ) ; HttpNetworkTransaction trans ( DEFAULT_PRIORITY , session_ . get ( ) ) ; TestCompletionCallback callback ; request_ . network_isolation_key = kNetworkIsolationKey1 ; int rv = trans . Start ( & request_ , callback . callback ( ) , net_log_ . bound ( ) ) ; EXPECT_THAT ( rv , IsError ( ERR_IO_PENDING ) ) ; base :: RunLoop ( ) . RunUntilIdle ( ) ; crypto_client_stream_factory_ . last_stream ( ) -> NotifySessionOneRttKeyAvailable ( ) ; quic_data . Resume ( ) ; base :: RunLoop ( ) . RunUntilIdle ( ) ; ASSERT_TRUE ( quic_data . AllWriteDataConsumed ( ) ) ; EXPECT_THAT ( callback . WaitForResult ( ) , IsOk ( ) ) ; ASSERT_TRUE ( quic_data . AllWriteDataConsumed ( ) ) ; ASSERT_FALSE ( http_data . AllReadDataConsumed ( ) ) ; CheckResponseData ( & trans , " " ) ; ASSERT_TRUE ( http_data . AllWriteDataConsumed ( ) ) ; ASSERT_TRUE ( http_data . AllReadDataConsumed ( ) ) ; ExpectBrokenAlternateProtocolMapping ( kNetworkIsolationKey1 ) ; ExpectQuicAlternateProtocolMapping ( kNetworkIsolationKey2 ) ; AddHttpDataAndRunRequest ( ) ; request_ . network_isolation_key = kNetworkIsolationKey2 ; AddQuicDataAndRunRequest ( ) ; ExpectBrokenAlternateProtocolMapping ( kNetworkIsolationKey1 ) ; ExpectQuicAlternateProtocolMapping ( kNetworkIsolationKey2 ) ; }
Much like above test, but verifies that NetworkIsolationKey is respected.
Much like above test but verifies that NetworkIsolationKey is respected .
// QUIC with TLS1.3 handshake doesn't support 0-rtt. // enabled_features // disabled_features // Since HttpServerProperties caches the feature value, have to create a new // one. // The request will initially go out over QUIC. // Pause // Peer sending data from an non-existing stream causes this end to raise // error and close connection. // After that fails, it will be resent via TCP. // In order for a new QUIC session to be established via alternate-protocol // without racing an HTTP connection, we need the host resolution to happen // synchronously.  Of course, even though QUIC *could* perform a 0-RTT // connection to the the server, in this test we require confirmation // before encrypting so the HTTP job will still start. // Pump the message loop to get the request started. // Explicitly confirm the handshake. // Run the QUIC session to completion. // Let the transaction proceed which will result in QUIC being marked // as broken and the request falling back to TCP. // Read the response body over TCP. // The alternative service shouldhave been marked as broken under // kNetworkIsolationKey1 but not kNetworkIsolationKey2. // Subsequent requests using kNetworkIsolationKey1 should not use QUIC. // Requests using other NetworkIsolationKeys can still use QUIC. // The last two requests should not have changed the alternative service // mappings.