| Index: net/quic/quic_network_transaction_unittest.cc
|
| diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
|
| index 4beb01dbff93a04014679744ca1779b77cc4dc63..b67d6461d8869ee626e5d36eecb9ebe4a2ee0cd7 100644
|
| --- a/net/quic/quic_network_transaction_unittest.cc
|
| +++ b/net/quic/quic_network_transaction_unittest.cc
|
| @@ -195,7 +195,6 @@ class QuicNetworkTransactionTest
|
| auth_handler_factory_(
|
| HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
|
| random_generator_(0),
|
| - hanging_data_(nullptr, 0, nullptr, 0),
|
| ssl_data_(ASYNC, OK) {
|
| request_.method = "GET";
|
| std::string url("https://");
|
| @@ -233,7 +232,25 @@ class QuicNetworkTransactionTest
|
| scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
|
| QuicPacketNumber largest_received,
|
| QuicPacketNumber least_unacked) {
|
| - return maker_.MakeAckPacket(2, largest_received, least_unacked, true);
|
| + return maker_.MakeAckPacket(2, largest_received, least_unacked,
|
| + least_unacked, true);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
|
| + QuicPacketNumber largest_received,
|
| + QuicPacketNumber least_unacked,
|
| + QuicTestPacketMaker* maker) {
|
| + return maker->MakeAckPacket(2, largest_received, least_unacked,
|
| + least_unacked, true);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructAckAndConnectionClosePacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicPacketNumber largest_received,
|
| + QuicPacketNumber ack_least_unacked,
|
| + QuicPacketNumber stop_least_unacked) {
|
| + return maker_.MakeAckPacket(packet_number, largest_received,
|
| + ack_least_unacked, stop_least_unacked, true);
|
| }
|
|
|
| scoped_ptr<QuicEncryptedPacket> ConstructAckAndConnectionClosePacket(
|
| @@ -256,16 +273,31 @@ class QuicNetworkTransactionTest
|
| return maker_.MakeRstPacket(num, include_version, stream_id, error_code);
|
| }
|
|
|
| + // Uses default QuicTestPacketMaker.
|
| SpdyHeaderBlock GetRequestHeaders(const std::string& method,
|
| const std::string& scheme,
|
| const std::string& path) {
|
| - return maker_.GetRequestHeaders(method, scheme, path);
|
| + return GetRequestHeaders(method, scheme, path, maker_);
|
| + }
|
| +
|
| + // Uses customized QuicTestPacketMaker.
|
| + SpdyHeaderBlock GetRequestHeaders(const std::string& method,
|
| + const std::string& scheme,
|
| + const std::string& path,
|
| + QuicTestPacketMaker& maker) {
|
| + return maker.GetRequestHeaders(method, scheme, path);
|
| }
|
|
|
| SpdyHeaderBlock GetResponseHeaders(const std::string& status) {
|
| return maker_.GetResponseHeaders(status);
|
| }
|
|
|
| + // Appends alt_svc headers in the response headers.
|
| + SpdyHeaderBlock GetResponseHeaders(const std::string& status,
|
| + const std::string& alt_svc) {
|
| + return maker_.GetResponseHeaders(status, alt_svc);
|
| + }
|
| +
|
| scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
|
| QuicPacketNumber packet_number,
|
| QuicStreamId stream_id,
|
| @@ -282,12 +314,50 @@ class QuicNetworkTransactionTest
|
| QuicStreamId stream_id,
|
| bool should_include_version,
|
| bool fin,
|
| - const SpdyHeaderBlock& headers) {
|
| + const SpdyHeaderBlock& headers,
|
| + QuicStreamOffset* offset) {
|
| SpdyPriority priority =
|
| ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
|
| - return maker_.MakeRequestHeadersPacket(packet_number, stream_id,
|
| - should_include_version, fin,
|
| - priority, headers);
|
| + return maker_.MakeRequestHeadersPacketWithOffsetTracking(
|
| + packet_number, stream_id, should_include_version, fin, priority,
|
| + headers, offset);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers,
|
| + QuicStreamOffset* offset,
|
| + QuicTestPacketMaker* maker) {
|
| + SpdyPriority priority =
|
| + ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
|
| + return maker->MakeRequestHeadersPacketWithOffsetTracking(
|
| + packet_number, stream_id, should_include_version, fin, priority,
|
| + headers, offset);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers) {
|
| + return ConstructRequestHeadersPacket(packet_number, stream_id,
|
| + should_include_version, fin, headers,
|
| + nullptr, &maker_);
|
| + }
|
| + scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers,
|
| + QuicTestPacketMaker* maker) {
|
| + return ConstructRequestHeadersPacket(packet_number, stream_id,
|
| + should_include_version, fin, headers,
|
| + nullptr, maker);
|
| }
|
|
|
| scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
|
| @@ -296,8 +366,44 @@ class QuicNetworkTransactionTest
|
| bool should_include_version,
|
| bool fin,
|
| const SpdyHeaderBlock& headers) {
|
| - return maker_.MakeResponseHeadersPacket(
|
| - packet_number, stream_id, should_include_version, fin, headers);
|
| + return ConstructResponseHeadersPacket(packet_number, stream_id,
|
| + should_include_version, fin, headers,
|
| + nullptr, &maker_);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers,
|
| + QuicTestPacketMaker* maker) {
|
| + return ConstructResponseHeadersPacket(packet_number, stream_id,
|
| + should_include_version, fin, headers,
|
| + nullptr, maker);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers,
|
| + QuicStreamOffset* offset) {
|
| + return maker_.MakeResponseHeadersPacketWithOffsetTracking(
|
| + packet_number, stream_id, should_include_version, fin, headers, offset);
|
| + }
|
| +
|
| + scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
|
| + QuicPacketNumber packet_number,
|
| + QuicStreamId stream_id,
|
| + bool should_include_version,
|
| + bool fin,
|
| + const SpdyHeaderBlock& headers,
|
| + QuicStreamOffset* offset,
|
| + QuicTestPacketMaker* maker) {
|
| + return maker->MakeResponseHeadersPacketWithOffsetTracking(
|
| + packet_number, stream_id, should_include_version, fin, headers, offset);
|
| }
|
|
|
| void CreateSession() { CreateSessionWithFactory(&socket_factory_, false); }
|
| @@ -433,9 +539,12 @@ class QuicNetworkTransactionTest
|
| }
|
|
|
| void AddHangingNonAlternateProtocolSocketData() {
|
| + scoped_ptr<StaticSocketDataProvider> hanging_data;
|
| + hanging_data.reset(new StaticSocketDataProvider());
|
| MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
|
| - hanging_data_.set_connect_data(hanging_connect);
|
| - socket_factory_.AddSocketDataProvider(&hanging_data_);
|
| + hanging_data->set_connect_data(hanging_connect);
|
| + hanging_data_.push_back(std::move(hanging_data));
|
| + socket_factory_.AddSocketDataProvider(hanging_data_.back().get());
|
| socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| }
|
|
|
| @@ -459,7 +568,7 @@ class QuicNetworkTransactionTest
|
| HttpNetworkSession::Params params_;
|
| HttpRequestInfo request_;
|
| BoundTestNetLog net_log_;
|
| - StaticSocketDataProvider hanging_data_;
|
| + std::vector<scoped_ptr<StaticSocketDataProvider>> hanging_data_;
|
| SSLSocketDataProvider ssl_data_;
|
|
|
| private:
|
| @@ -635,6 +744,7 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
|
| mock_quic_data1.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
|
|
|
| MockQuicData mock_quic_data2;
|
| + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
|
| mock_quic_data2.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
|
| crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
|
|
|
| @@ -768,14 +878,13 @@ TEST_P(QuicNetworkTransactionTest,
|
| }
|
|
|
| // When multiple alternative services are advertised,
|
| -// HttpStreamFactoryImpl::RequestStreamInternal() only passes the first one to
|
| -// Job. This is what the following test verifies.
|
| -// TODO(bnc): Update this test when multiple alternative services are handled
|
| -// properly.
|
| -TEST_P(QuicNetworkTransactionTest, UseFirstAlternativeServiceForQuic) {
|
| +// HttpStreamFactoryImpl::RequestStreamInternal() should select the alternative
|
| +// service which uses existing QUIC session if available. If no existing QUIC
|
| +// session can be used, use the first alternative service from the list.
|
| +TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
|
| MockRead http_reads[] = {
|
| MockRead("HTTP/1.1 200 OK\r\n"),
|
| - MockRead("Alt-Svc: quic=\":443\", quic=\":1234\"\r\n\r\n"),
|
| + MockRead("Alt-Svc: quic=\"foo.example.com:443\", quic=\":444\"\r\n\r\n"),
|
| MockRead("hello world"),
|
| MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| MockRead(ASYNC, OK)};
|
| @@ -785,15 +894,38 @@ TEST_P(QuicNetworkTransactionTest, UseFirstAlternativeServiceForQuic) {
|
| socket_factory_.AddSocketDataProvider(&http_data);
|
| socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
|
|
| + QuicStreamOffset request_header_offset = 0;
|
| + QuicStreamOffset response_header_offset = 0;
|
| + // First QUIC request data.
|
| + // Open a session to foo.example.com:443 using the first entry of the
|
| + // alternative service list.
|
| MockQuicData mock_quic_data;
|
| - mock_quic_data.AddWrite(
|
| - ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
|
| - GetRequestHeaders("GET", "https", "/")));
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/"), &request_header_offset));
|
| +
|
| + std::string alt_svc_list =
|
| + "quic=\"mail.example.com:444\", quic=\"foo.example.com:443\", "
|
| + "quic=\"bar.example.com:445\"";
|
| mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| - 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
|
| + 1, kClientDataStreamId1, false, false,
|
| + GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
|
| mock_quic_data.AddRead(
|
| ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
|
| mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
|
| +
|
| + // Second QUIC request data.
|
| + // Connection pooling, using existing session, no need to include version
|
| + // as version negotiation has been completed.
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 3, kClientDataStreamId2, false, true,
|
| + GetRequestHeaders("GET", "https", "/"), &request_header_offset));
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
|
| + &response_header_offset));
|
| + mock_quic_data.AddRead(
|
| + ConstructDataPacket(4, kClientDataStreamId2, false, true, 0, "hello!"));
|
| + mock_quic_data.AddWrite(ConstructAckAndConnectionClosePacket(4, 4, 3, 1));
|
| mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| mock_quic_data.AddRead(ASYNC, 0); // EOF
|
|
|
| @@ -803,7 +935,283 @@ TEST_P(QuicNetworkTransactionTest, UseFirstAlternativeServiceForQuic) {
|
| CreateSessionWithNextProtos();
|
|
|
| SendRequestAndExpectHttpResponse("hello world");
|
| +
|
| SendRequestAndExpectQuicResponseOnPort("hello!", 443);
|
| + SendRequestAndExpectQuicResponseOnPort("hello!", 443);
|
| +}
|
| +
|
| +// When multiple alternative services that has existing QUIC session.
|
| +// HttpStreamFactoryImpl::RequestStreamInternal() should select the first
|
| +// alternative service which uses existing QUIC session.
|
| +TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
|
| + MockRead http_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"),
|
| + MockRead("Alt-Svc: quic=\"foo.example.com:443\", quic=\":446\"\r\n\r\n"),
|
| + MockRead("hello world"),
|
| + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| + MockRead(ASYNC, OK)};
|
| +
|
| + StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
|
| + 0);
|
| + socket_factory_.AddSocketDataProvider(&http_data);
|
| + socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| +
|
| + QuicStreamOffset request_header_offset = 0;
|
| + QuicStreamOffset response_header_offset = 0;
|
| +
|
| + QuicTestPacketMaker maker(GetParam(), 0, clock_, kDefaultServerHostName);
|
| +
|
| + MockQuicData mock_quic_data;
|
| + MockQuicData mock_quic_data2;
|
| + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
|
| + // First QUIC request data.
|
| + // Open a QUIC session to foo.example.com:443.
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/"), &request_header_offset));
|
| +
|
| + std::string alt_svc_list =
|
| + "quic=\"bar.example.com:444\", quic=\"frog.example.com:445\", "
|
| + "quic=\"mail.example.com:446\"";
|
| + // Response header from the server resets the alt_svc list for the origin.
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 1, kClientDataStreamId1, false, false,
|
| + GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
|
| + mock_quic_data.AddRead(ConstructDataPacket(2, kClientDataStreamId1, false,
|
| + true, 0, "hello from foo!"));
|
| + mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
|
| +
|
| + // Second QUIC request data.
|
| + // Existing QUIC session to foo.example.com is not viable from the updated
|
| + // alt_svc. Unable to pool the existing QUIC session.
|
| + // Open a new QUIC session to bar.example.com:443.
|
| + mock_quic_data2.AddWrite(ConstructRequestHeadersPacket(
|
| + 1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/"), &maker));
|
| + alt_svc_list =
|
| + "quic=\"foo.example.com:443\", quic=\"mail.example.com:446\", "
|
| + "quic=\"bar.example.com:444\"";
|
| + // Response header from the server resets the alt_svc list for the origin.
|
| + mock_quic_data2.AddRead(ConstructResponseHeadersPacket(
|
| + 1, kClientDataStreamId1, false, false,
|
| + GetResponseHeaders("200 OK", alt_svc_list), &maker));
|
| + mock_quic_data2.AddRead(ConstructDataPacket(2, kClientDataStreamId1, false,
|
| + true, 0, "hello from bar!"));
|
| + mock_quic_data2.AddWrite(ConstructAckPacket(2, 1, &maker));
|
| + mock_quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| + mock_quic_data2.AddRead(ASYNC, 0); // EOF
|
| +
|
| + // Third QUIC request data.
|
| + // Connection pooling, using the first existing session to foo.example.com
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 3, kClientDataStreamId2, false, true,
|
| + GetRequestHeaders("GET", "https", "/"), &request_header_offset));
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
|
| + &response_header_offset));
|
| + mock_quic_data.AddRead(ConstructDataPacket(4, kClientDataStreamId2, false,
|
| + true, 0, "hello from foo!"));
|
| + mock_quic_data.AddWrite(ConstructAckAndConnectionClosePacket(4, 4, 3, 1));
|
| + mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| + mock_quic_data.AddRead(ASYNC, 0); // EOF
|
| +
|
| + mock_quic_data.AddSocketDataToFactory(&socket_factory_);
|
| + AddHangingNonAlternateProtocolSocketData();
|
| +
|
| + mock_quic_data2.AddSocketDataToFactory(&socket_factory_);
|
| +
|
| + AddHangingNonAlternateProtocolSocketData();
|
| +
|
| + CreateSessionWithNextProtos();
|
| +
|
| + SendRequestAndExpectHttpResponse("hello world");
|
| + SendRequestAndExpectQuicResponseOnPort("hello from foo!", 443);
|
| + SendRequestAndExpectQuicResponseOnPort("hello from bar!", 444);
|
| + SendRequestAndExpectQuicResponseOnPort("hello from foo!", 443);
|
| +}
|
| +
|
| +// Multiple origins have listed the same alternative services. When there's a
|
| +// existing QUIC session opened by a request to other origin,
|
| +// if the cert is valid, should select this QUIC session to make the request
|
| +// if this is also the first existing QUIC session.
|
| +TEST_P(QuicNetworkTransactionTest,
|
| + UseSharedExistingAlternativeServiceForQuicWithValidCert) {
|
| + // Default cert is valid for the following origins:
|
| + // mail.example.com, mail.example.org, and www.example.org.
|
| +
|
| + // HTTP data for request to mail.example.com.
|
| + MockRead http_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"),
|
| + MockRead("Alt-Svc: quic=\":443\"\r\n\r\n"),
|
| + MockRead("hello world from mail.example.com"),
|
| + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| + MockRead(ASYNC, OK)};
|
| +
|
| + StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
|
| + 0);
|
| + socket_factory_.AddSocketDataProvider(&http_data);
|
| + socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| +
|
| + // HTTP data for request to mail.example.org.
|
| + MockRead http_reads2[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"),
|
| + MockRead("Alt-Svc: quic=\":444\", quic=\"mail.example.com:443\"\r\n\r\n"),
|
| + MockRead("hello world from mail.example.org"),
|
| + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| + MockRead(ASYNC, OK)};
|
| +
|
| + StaticSocketDataProvider http_data2(http_reads2, arraysize(http_reads2),
|
| + nullptr, 0);
|
| + socket_factory_.AddSocketDataProvider(&http_data2);
|
| + socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| +
|
| + QuicStreamOffset request_header_offset = 0;
|
| + QuicStreamOffset response_header_offset = 0;
|
| +
|
| + QuicTestPacketMaker maker(GetParam(), 0, clock_, kDefaultServerHostName);
|
| + maker.set_hostname("mail.example.org");
|
| + MockQuicData mock_quic_data;
|
| +
|
| + // First QUIC request data.
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/"), &request_header_offset));
|
| +
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK"),
|
| + &response_header_offset));
|
| + mock_quic_data.AddRead(ConstructDataPacket(2, kClientDataStreamId1, false,
|
| + true, 0, "hello from mail QUIC!"));
|
| + mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
|
| +
|
| + // Second QUIC request data.
|
| + mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
|
| + 3, kClientDataStreamId2, false, true,
|
| + GetRequestHeaders("GET", "https", "/", maker), &request_header_offset,
|
| + &maker));
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
|
| + &response_header_offset));
|
| + mock_quic_data.AddRead(ConstructDataPacket(4, kClientDataStreamId2, false,
|
| + true, 0, "hello from mail QUIC!"));
|
| + mock_quic_data.AddWrite(ConstructAckAndConnectionClosePacket(4, 4, 3, 1));
|
| + mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| + mock_quic_data.AddRead(ASYNC, 0); // EOF
|
| +
|
| + mock_quic_data.AddSocketDataToFactory(&socket_factory_);
|
| + AddHangingNonAlternateProtocolSocketData();
|
| +
|
| + CreateSessionWithNextProtos();
|
| +
|
| + // Send two HTTP requests, responses set up alt-svc lists for the origins.
|
| + SendRequestAndExpectHttpResponse("hello world from mail.example.com");
|
| + request_.url = GURL("https://mail.example.org/");
|
| + SendRequestAndExpectHttpResponse("hello world from mail.example.org");
|
| +
|
| + // Open a QUIC session to mail.example.com:443 when making request
|
| + // to mail.example.com.
|
| + request_.url = GURL("https://mail.example.com/");
|
| + SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
|
| +
|
| + // Uses the existing QUIC session when making request to mail.example.org.
|
| + request_.url = GURL("https://mail.example.org/");
|
| + SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
|
| +}
|
| +
|
| +// Multiple origins have listed the same alternative services. When there's a
|
| +// existing QUIC session opened by a request to other origin,
|
| +// if the cert is NOT valid, should ignore this QUIC session.
|
| +TEST_P(QuicNetworkTransactionTest,
|
| + DoNotUseSharedExistingAlternativeServiceForQuicWithInvalidCert) {
|
| + // Default cert is only valid for the following origins:
|
| + // mail.example.com, mail.example.org, and www.example.org.
|
| + // NOT valid for docs.example.org.
|
| +
|
| + // HTTP data for request to mail.example.com.
|
| + MockRead http_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"),
|
| + MockRead("Alt-Svc: quic=\":443\"\r\n\r\n"),
|
| + MockRead("hello world from mail.example.com"),
|
| + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| + MockRead(ASYNC, OK)};
|
| +
|
| + StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
|
| + 0);
|
| + socket_factory_.AddSocketDataProvider(&http_data);
|
| + socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| +
|
| + // HTTP data for request to docs.example.org.
|
| + MockRead http_reads2[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"),
|
| + MockRead("Alt-Svc: quic=\":444\", quic=\"mail.example.com:443\"\r\n\r\n"),
|
| + MockRead("hello world from docs.example.org"),
|
| + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
|
| + MockRead(ASYNC, OK)};
|
| +
|
| + StaticSocketDataProvider http_data2(http_reads2, arraysize(http_reads2),
|
| + nullptr, 0);
|
| + socket_factory_.AddSocketDataProvider(&http_data2);
|
| + socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
|
| +
|
| + QuicTestPacketMaker maker(GetParam(), 0, clock_, kDefaultServerHostName);
|
| + maker.set_hostname("docs.example.org");
|
| + MockQuicData mock_quic_data;
|
| + MockQuicData mock_quic_data2;
|
| +
|
| + // Adding a valid cert for *.example.org but not mail.example.com.
|
| + ProofVerifyDetailsChromium verify_details;
|
| + scoped_refptr<X509Certificate> cert(
|
| + ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
|
| + verify_details.cert_verify_result.verified_cert = cert;
|
| + verify_details.cert_verify_result.is_issued_by_known_root = true;
|
| + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
|
| +
|
| + // First QUIC request data.
|
| + mock_quic_data.AddWrite(
|
| + ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/")));
|
| + mock_quic_data.AddRead(ConstructResponseHeadersPacket(
|
| + 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
|
| + mock_quic_data.AddRead(ConstructDataPacket(2, kClientDataStreamId1, false,
|
| + true, 0, "hello from mail QUIC!"));
|
| + mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
|
| + mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| + mock_quic_data.AddRead(ASYNC, 0); // EOF
|
| +
|
| + // First QUIC request data.
|
| + mock_quic_data2.AddWrite(ConstructRequestHeadersPacket(
|
| + 1, kClientDataStreamId1, true, true,
|
| + GetRequestHeaders("GET", "https", "/", maker), &maker));
|
| + mock_quic_data2.AddRead(
|
| + ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
|
| + GetResponseHeaders("200 OK"), &maker));
|
| + mock_quic_data2.AddRead(ConstructDataPacket(
|
| + 2, kClientDataStreamId1, false, true, 0, "hello from docs QUIC!"));
|
| + mock_quic_data2.AddWrite(ConstructAckPacket(2, 1, &maker));
|
| + mock_quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
|
| + mock_quic_data2.AddRead(ASYNC, 0); // EOF
|
| +
|
| + mock_quic_data.AddSocketDataToFactory(&socket_factory_);
|
| + AddHangingNonAlternateProtocolSocketData();
|
| +
|
| + mock_quic_data2.AddSocketDataToFactory(&socket_factory_);
|
| + AddHangingNonAlternateProtocolSocketData();
|
| +
|
| + CreateSessionWithNextProtos();
|
| +
|
| + // Send HTTP requests, responses set up the alt-svc lists for the origins.
|
| + SendRequestAndExpectHttpResponse("hello world from mail.example.com");
|
| + request_.url = GURL("https://docs.example.org/");
|
| + SendRequestAndExpectHttpResponse("hello world from docs.example.org");
|
| +
|
| + // Open a QUIC session to mail.example.com:443 when making request
|
| + // to mail.example.com.
|
| + request_.url = GURL("https://mail.example.com/");
|
| + SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
|
| +
|
| + // Open another new QUIC session to docs.example.org:444.
|
| + request_.url = GURL("https://docs.example.org/");
|
| + SendRequestAndExpectQuicResponseOnPort("hello from docs QUIC!", 444);
|
| }
|
|
|
| TEST_P(QuicNetworkTransactionTest, AlternativeServiceDifferentPort) {
|
|
|