| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <memory> | 6 #include <memory> |
| 7 #include <ostream> | 7 #include <ostream> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 2558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2569 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); | 2569 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); |
| 2570 ASSERT_FALSE(http_data.AllReadDataConsumed()); | 2570 ASSERT_FALSE(http_data.AllReadDataConsumed()); |
| 2571 | 2571 |
| 2572 // Read the response body over TCP. | 2572 // Read the response body over TCP. |
| 2573 CheckResponseData(&trans, "hello world"); | 2573 CheckResponseData(&trans, "hello world"); |
| 2574 ExpectBrokenAlternateProtocolMapping(); | 2574 ExpectBrokenAlternateProtocolMapping(); |
| 2575 ASSERT_TRUE(http_data.AllWriteDataConsumed()); | 2575 ASSERT_TRUE(http_data.AllWriteDataConsumed()); |
| 2576 ASSERT_TRUE(http_data.AllReadDataConsumed()); | 2576 ASSERT_TRUE(http_data.AllReadDataConsumed()); |
| 2577 } | 2577 } |
| 2578 | 2578 |
| 2579 // Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC |
| 2580 // request is reset from, then QUIC will be marked as broken and the request |
| 2581 // retried over TCP. |
| 2582 TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) { |
| 2583 session_params_.retry_without_alt_svc_on_quic_errors = true; |
| 2584 |
| 2585 // The request will initially go out over QUIC. |
| 2586 MockQuicData quic_data; |
| 2587 QuicStreamOffset header_stream_offset = 0; |
| 2588 SpdyPriority priority = |
| 2589 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); |
| 2590 |
| 2591 std::string request_data; |
| 2592 quic_data.AddWrite(client_maker_.MakeRequestHeadersPacketAndSaveData( |
| 2593 1, GetNthClientInitiatedStreamId(0), true, true, priority, |
| 2594 GetRequestHeaders("GET", "https", "/"), nullptr, &header_stream_offset, |
| 2595 &request_data)); |
| 2596 |
| 2597 std::string settings_data; |
| 2598 // QuicStreamOffset settings_offset = header_stream_offset; |
| 2599 quic_data.AddWrite(client_maker_.MakeInitialSettingsPacketAndSaveData( |
| 2600 2, &header_stream_offset, &settings_data)); |
| 2601 |
| 2602 quic_data.AddRead(ConstructServerRstPacket( |
| 2603 1, false, GetNthClientInitiatedStreamId(0), QUIC_HEADERS_TOO_LARGE)); |
| 2604 |
| 2605 quic_data.AddRead(ASYNC, OK); |
| 2606 quic_data.AddSocketDataToFactory(&socket_factory_); |
| 2607 |
| 2608 // After that fails, it will be resent via TCP. |
| 2609 MockWrite http_writes[] = { |
| 2610 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), |
| 2611 MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"), |
| 2612 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")}; |
| 2613 |
| 2614 MockRead http_reads[] = { |
| 2615 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), |
| 2616 MockRead(SYNCHRONOUS, 4, kQuicAlternativeServiceHeader), |
| 2617 MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)}; |
| 2618 SequencedSocketData http_data(http_reads, arraysize(http_reads), http_writes, |
| 2619 arraysize(http_writes)); |
| 2620 socket_factory_.AddSocketDataProvider(&http_data); |
| 2621 socket_factory_.AddSSLSocketDataProvider(&ssl_data_); |
| 2622 |
| 2623 // In order for a new QUIC session to be established via alternate-protocol |
| 2624 // without racing an HTTP connection, we need the host resolution to happen |
| 2625 // synchronously. Of course, even though QUIC *could* perform a 0-RTT |
| 2626 // connection to the the server, in this test we require confirmation |
| 2627 // before encrypting so the HTTP job will still start. |
| 2628 host_resolver_.set_synchronous_mode(true); |
| 2629 host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", |
| 2630 ""); |
| 2631 HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); |
| 2632 AddressList address; |
| 2633 std::unique_ptr<HostResolver::Request> request; |
| 2634 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(), |
| 2635 &request, net_log_.bound()); |
| 2636 |
| 2637 CreateSession(); |
| 2638 |
| 2639 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); |
| 2640 |
| 2641 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); |
| 2642 TestCompletionCallback callback; |
| 2643 int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); |
| 2644 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
| 2645 |
| 2646 // Pump the message loop to get the request started. |
| 2647 base::RunLoop().RunUntilIdle(); |
| 2648 // Explicitly confirm the handshake. |
| 2649 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( |
| 2650 QuicSession::HANDSHAKE_CONFIRMED); |
| 2651 |
| 2652 // Run the QUIC session to completion. |
| 2653 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); |
| 2654 |
| 2655 ExpectQuicAlternateProtocolMapping(); |
| 2656 |
| 2657 // Let the transaction proceed which will result in QUIC being marked |
| 2658 // as broken and the request falling back to TCP. |
| 2659 EXPECT_THAT(callback.WaitForResult(), IsOk()); |
| 2660 |
| 2661 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); |
| 2662 ASSERT_FALSE(http_data.AllReadDataConsumed()); |
| 2663 |
| 2664 // Read the response body over TCP. |
| 2665 CheckResponseData(&trans, "hello world"); |
| 2666 ExpectBrokenAlternateProtocolMapping(); |
| 2667 ASSERT_TRUE(http_data.AllWriteDataConsumed()); |
| 2668 ASSERT_TRUE(http_data.AllReadDataConsumed()); |
| 2669 } |
| 2670 |
| 2671 // Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC |
| 2672 // request is reset from, then QUIC will be marked as broken and the request |
| 2673 // retried over TCP. Then, subsequent requests will go over a new QUIC |
| 2674 // connection instead of going back to the broken QUIC connection. |
| 2675 // This is a regression tests for crbug/731303. |
| 2676 TEST_P(QuicNetworkTransactionTest, |
| 2677 ResetPooledAfterHandshakeConfirmedThenBroken) { |
| 2678 session_params_.retry_without_alt_svc_on_quic_errors = true; |
| 2679 |
| 2680 GURL origin1 = request_.url; |
| 2681 GURL origin2("https://www.example.org/"); |
| 2682 ASSERT_NE(origin1.host(), origin2.host()); |
| 2683 |
| 2684 MockQuicData mock_quic_data; |
| 2685 QuicStreamOffset request_header_offset(0); |
| 2686 QuicStreamOffset response_header_offset(0); |
| 2687 |
| 2688 scoped_refptr<X509Certificate> cert( |
| 2689 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); |
| 2690 ASSERT_TRUE(cert->VerifyNameMatch("www.example.org", false)); |
| 2691 ASSERT_TRUE(cert->VerifyNameMatch("mail.example.org", false)); |
| 2692 |
| 2693 ProofVerifyDetailsChromium verify_details; |
| 2694 verify_details.cert_verify_result.verified_cert = cert; |
| 2695 verify_details.cert_verify_result.is_issued_by_known_root = true; |
| 2696 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); |
| 2697 |
| 2698 mock_quic_data.AddWrite( |
| 2699 ConstructInitialSettingsPacket(1, &request_header_offset)); |
| 2700 // First request. |
| 2701 mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket( |
| 2702 2, GetNthClientInitiatedStreamId(0), true, true, |
| 2703 GetRequestHeaders("GET", "https", "/"), &request_header_offset)); |
| 2704 mock_quic_data.AddRead(ConstructServerResponseHeadersPacket( |
| 2705 1, GetNthClientInitiatedStreamId(0), false, false, |
| 2706 GetResponseHeaders("200 OK"), &response_header_offset)); |
| 2707 mock_quic_data.AddRead(ConstructServerDataPacket( |
| 2708 2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!")); |
| 2709 mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1)); |
| 2710 |
| 2711 // Second request will go over the pooled QUIC connection, but will be |
| 2712 // reset by the server. |
| 2713 QuicTestPacketMaker client_maker2(version_, 0, &clock_, origin2.host(), |
| 2714 Perspective::IS_CLIENT); |
| 2715 QuicTestPacketMaker server_maker2(version_, 0, &clock_, origin2.host(), |
| 2716 Perspective::IS_SERVER); |
| 2717 mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket( |
| 2718 4, GetNthClientInitiatedStreamId(1), false, true, |
| 2719 GetRequestHeaders("GET", "https", "/", &client_maker2), |
| 2720 &request_header_offset)); |
| 2721 mock_quic_data.AddRead(ConstructServerRstPacket( |
| 2722 3, false, GetNthClientInitiatedStreamId(1), QUIC_HEADERS_TOO_LARGE)); |
| 2723 mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read |
| 2724 mock_quic_data.AddRead(ASYNC, 0); // EOF |
| 2725 |
| 2726 mock_quic_data.AddSocketDataToFactory(&socket_factory_); |
| 2727 |
| 2728 // After that fails, it will be resent via TCP. |
| 2729 MockWrite http_writes[] = { |
| 2730 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), |
| 2731 MockWrite(SYNCHRONOUS, 1, "Host: www.example.org\r\n"), |
| 2732 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")}; |
| 2733 |
| 2734 MockRead http_reads[] = { |
| 2735 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), |
| 2736 MockRead(SYNCHRONOUS, 4, kQuicAlternativeServiceHeader), |
| 2737 MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)}; |
| 2738 SequencedSocketData http_data(http_reads, arraysize(http_reads), http_writes, |
| 2739 arraysize(http_writes)); |
| 2740 socket_factory_.AddSocketDataProvider(&http_data); |
| 2741 socket_factory_.AddSSLSocketDataProvider(&ssl_data_); |
| 2742 |
| 2743 // Then the next request to the second origin will go over a new QUIC |
| 2744 // connection. |
| 2745 MockQuicData mock_quic_data2; |
| 2746 QuicTestPacketMaker client_maker3(version_, 0, &clock_, origin2.host(), |
| 2747 Perspective::IS_CLIENT); |
| 2748 QuicTestPacketMaker server_maker3(version_, 0, &clock_, origin2.host(), |
| 2749 Perspective::IS_SERVER); |
| 2750 QuicStreamOffset request_header_offset2(0); |
| 2751 QuicStreamOffset response_header_offset2(0); |
| 2752 |
| 2753 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); |
| 2754 |
| 2755 mock_quic_data2.AddWrite( |
| 2756 client_maker3.MakeInitialSettingsPacket(1, &request_header_offset2)); |
| 2757 mock_quic_data2.AddWrite( |
| 2758 client_maker3.MakeRequestHeadersPacketWithOffsetTracking( |
| 2759 2, GetNthClientInitiatedStreamId(0), true, true, |
| 2760 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY), |
| 2761 GetRequestHeaders("GET", "https", "/", &client_maker3), |
| 2762 &request_header_offset2)); |
| 2763 mock_quic_data2.AddRead( |
| 2764 server_maker2.MakeResponseHeadersPacketWithOffsetTracking( |
| 2765 1, GetNthClientInitiatedStreamId(0), false, false, |
| 2766 GetResponseHeaders("200 OK"), &response_header_offset2)); |
| 2767 mock_quic_data2.AddRead(server_maker2.MakeDataPacket( |
| 2768 2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!")); |
| 2769 mock_quic_data2.AddWrite(ConstructClientAckPacket(3, 2, 1, 1)); |
| 2770 mock_quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read |
| 2771 mock_quic_data2.AddRead(ASYNC, 0); // EOF |
| 2772 |
| 2773 mock_quic_data2.AddSocketDataToFactory(&socket_factory_); |
| 2774 |
| 2775 CreateSession(); |
| 2776 |
| 2777 // Set up alternative service for |origin1|. |
| 2778 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); |
| 2779 http_server_properties_.SetAlternativeService( |
| 2780 url::SchemeHostPort(origin1), |
| 2781 AlternativeService(kProtoQUIC, "mail.example.com", 443), expiration); |
| 2782 |
| 2783 // Set up alternative service for |origin2|. |
| 2784 AlternativeServiceInfoVector alternative_services; |
| 2785 http_server_properties_.SetAlternativeService( |
| 2786 url::SchemeHostPort(origin2), |
| 2787 AlternativeService(kProtoQUIC, "www.example.com", 443), expiration); |
| 2788 // First request opens connection to |destination1| |
| 2789 // with QuicServerId.host() == origin1.host(). |
| 2790 SendRequestAndExpectQuicResponse("hello!"); |
| 2791 |
| 2792 // Second request pools to existing connection with same destination, |
| 2793 // because certificate matches, even though QuicServerId is different. |
| 2794 // After it is reset, it will fail back to QUIC and mark QUIC as broken. |
| 2795 request_.url = origin2; |
| 2796 SendRequestAndExpectHttpResponse("hello world"); |
| 2797 |
| 2798 // The third request should use a new QUIC connection, not the broken |
| 2799 // QUIC connection. |
| 2800 SendRequestAndExpectQuicResponse("hello!"); |
| 2801 } |
| 2802 |
| 2579 TEST_P(QuicNetworkTransactionTest, | 2803 TEST_P(QuicNetworkTransactionTest, |
| 2580 DoNotUseAlternativeServiceQuicUnsupportedVersion) { | 2804 DoNotUseAlternativeServiceQuicUnsupportedVersion) { |
| 2581 std::string altsvc_header = base::StringPrintf( | 2805 std::string altsvc_header = base::StringPrintf( |
| 2582 "Alt-Svc: quic=\":443\"; v=\"%u\"\r\n\r\n", version_ - 1); | 2806 "Alt-Svc: quic=\":443\"; v=\"%u\"\r\n\r\n", version_ - 1); |
| 2583 MockRead http_reads[] = { | 2807 MockRead http_reads[] = { |
| 2584 MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()), | 2808 MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()), |
| 2585 MockRead("hello world"), | 2809 MockRead("hello world"), |
| 2586 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | 2810 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), |
| 2587 MockRead(ASYNC, OK)}; | 2811 MockRead(ASYNC, OK)}; |
| 2588 | 2812 |
| (...skipping 2213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4802 | 5026 |
| 4803 request_.url = GURL("https://mail.example.org/pushed.jpg"); | 5027 request_.url = GURL("https://mail.example.org/pushed.jpg"); |
| 4804 ChunkedUploadDataStream upload_data(0); | 5028 ChunkedUploadDataStream upload_data(0); |
| 4805 upload_data.AppendData("1", 1, true); | 5029 upload_data.AppendData("1", 1, true); |
| 4806 request_.upload_data_stream = &upload_data; | 5030 request_.upload_data_stream = &upload_data; |
| 4807 SendRequestAndExpectQuicResponse("and hello!"); | 5031 SendRequestAndExpectQuicResponse("and hello!"); |
| 4808 } | 5032 } |
| 4809 | 5033 |
| 4810 } // namespace test | 5034 } // namespace test |
| 4811 } // namespace net | 5035 } // namespace net |
| OLD | NEW |