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 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "base/basictypes.h" 8 #include "base/compiler_specific.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/stl_util.h" 11 #include "net/base/capturing_net_log.h" 12 #include "net/base/net_log_unittest.h" 13 #include "net/base/test_completion_callback.h" 14 #include "net/cert/mock_cert_verifier.h" 15 #include "net/dns/mock_host_resolver.h" 16 #include "net/http/http_auth_handler_factory.h" 17 #include "net/http/http_network_session.h" 18 #include "net/http/http_network_transaction.h" 19 #include "net/http/http_server_properties_impl.h" 20 #include "net/http/http_stream.h" 21 #include "net/http/http_stream_factory.h" 22 #include "net/http/http_transaction_test_util.h" 23 #include "net/http/transport_security_state.h" 24 #include "net/proxy/proxy_config_service_fixed.h" 25 #include "net/proxy/proxy_resolver.h" 26 #include "net/proxy/proxy_service.h" 27 #include "net/quic/crypto/quic_decrypter.h" 28 #include "net/quic/crypto/quic_encrypter.h" 29 #include "net/quic/quic_framer.h" 30 #include "net/quic/quic_http_utils.h" 31 #include "net/quic/test_tools/crypto_test_utils.h" 32 #include "net/quic/test_tools/mock_clock.h" 33 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h" 34 #include "net/quic/test_tools/mock_random.h" 35 #include "net/quic/test_tools/quic_test_packet_maker.h" 36 #include "net/quic/test_tools/quic_test_utils.h" 37 #include "net/socket/client_socket_factory.h" 38 #include "net/socket/mock_client_socket_pool_manager.h" 39 #include "net/socket/socket_test_util.h" 40 #include "net/socket/ssl_client_socket.h" 41 #include "net/spdy/spdy_frame_builder.h" 42 #include "net/spdy/spdy_framer.h" 43 #include "net/ssl/ssl_config_service_defaults.h" 44 #include "testing/gtest/include/gtest/gtest.h" 45 #include "testing/platform_test.h" 46 47 //----------------------------------------------------------------------------- 48 49 namespace { 50 51 // This is the expected return from a current server advertising QUIC. 52 static const char kQuicAlternateProtocolHttpHeader[] = 53 "Alternate-Protocol: 80:quic\r\n\r\n"; 54 static const char kQuicAlternateProtocolHttpsHeader[] = 55 "Alternate-Protocol: 443:quic\r\n\r\n"; 56 57 } // namespace 58 59 namespace net { 60 namespace test { 61 62 // Helper class to encapsulate MockReads and MockWrites for QUIC. 63 // Simplify ownership issues and the interaction with the MockSocketFactory. 64 class MockQuicData { 65 public: 66 ~MockQuicData() { 67 STLDeleteElements(&packets_); 68 } 69 70 void AddRead(scoped_ptr<QuicEncryptedPacket> packet) { 71 reads_.push_back(MockRead(SYNCHRONOUS, packet->data(), packet->length(), 72 sequence_number_++)); 73 packets_.push_back(packet.release()); 74 } 75 76 void AddRead(IoMode mode, int rv) { 77 reads_.push_back(MockRead(mode, rv)); 78 } 79 80 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) { 81 writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(), 82 sequence_number_++)); 83 packets_.push_back(packet.release()); 84 } 85 86 void AddDelayedSocketDataToFactory(MockClientSocketFactory* factory, 87 size_t delay) { 88 MockRead* reads = reads_.empty() ? NULL : &reads_[0]; 89 MockWrite* writes = writes_.empty() ? NULL : &writes_[0]; 90 socket_data_.reset(new DelayedSocketData( 91 delay, reads, reads_.size(), writes, writes_.size())); 92 factory->AddSocketDataProvider(socket_data_.get()); 93 } 94 95 private: 96 std::vector<QuicEncryptedPacket*> packets_; 97 std::vector<MockWrite> writes_; 98 std::vector<MockRead> reads_; 99 size_t sequence_number_; 100 scoped_ptr<SocketDataProvider> socket_data_; 101 }; 102 103 class QuicNetworkTransactionTest 104 : public PlatformTest, 105 public ::testing::WithParamInterface<QuicVersion> { 106 protected: 107 QuicNetworkTransactionTest() 108 : maker_(GetParam(), 0), 109 clock_(new MockClock), 110 ssl_config_service_(new SSLConfigServiceDefaults), 111 proxy_service_(ProxyService::CreateDirect()), 112 auth_handler_factory_( 113 HttpAuthHandlerFactory::CreateDefault(&host_resolver_)), 114 random_generator_(0), 115 hanging_data_(NULL, 0, NULL, 0) { 116 request_.method = "GET"; 117 request_.url = GURL("http://www.google.com/"); 118 request_.load_flags = 0; 119 clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); 120 } 121 122 virtual void SetUp() { 123 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 124 base::MessageLoop::current()->RunUntilIdle(); 125 } 126 127 virtual void TearDown() { 128 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 129 // Empty the current queue. 130 base::MessageLoop::current()->RunUntilIdle(); 131 PlatformTest::TearDown(); 132 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 133 base::MessageLoop::current()->RunUntilIdle(); 134 } 135 136 scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket( 137 QuicPacketSequenceNumber num) { 138 return maker_.MakeConnectionClosePacket(num); 139 } 140 141 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket( 142 QuicPacketSequenceNumber largest_received, 143 QuicPacketSequenceNumber least_unacked) { 144 return maker_.MakeAckPacket(2, largest_received, least_unacked, true); 145 } 146 147 SpdyHeaderBlock GetRequestHeaders(const std::string& method, 148 const std::string& scheme, 149 const std::string& path) { 150 return maker_.GetRequestHeaders(method, scheme, path); 151 } 152 153 SpdyHeaderBlock GetResponseHeaders(const std::string& status) { 154 return maker_.GetResponseHeaders(status); 155 } 156 157 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket( 158 QuicPacketSequenceNumber sequence_number, 159 QuicStreamId stream_id, 160 bool should_include_version, 161 bool fin, 162 QuicStreamOffset offset, 163 base::StringPiece data) { 164 return maker_.MakeDataPacket( 165 sequence_number, stream_id, should_include_version, fin, offset, data); 166 } 167 168 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket( 169 QuicPacketSequenceNumber sequence_number, 170 QuicStreamId stream_id, 171 bool should_include_version, 172 bool fin, 173 const SpdyHeaderBlock& headers) { 174 return maker_.MakeRequestHeadersPacket( 175 sequence_number, stream_id, should_include_version, fin, headers); 176 } 177 178 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket( 179 QuicPacketSequenceNumber sequence_number, 180 QuicStreamId stream_id, 181 bool should_include_version, 182 bool fin, 183 const SpdyHeaderBlock& headers) { 184 return maker_.MakeResponseHeadersPacket( 185 sequence_number, stream_id, should_include_version, fin, headers); 186 } 187 188 void CreateSession() { 189 CreateSessionWithFactory(&socket_factory_, false); 190 } 191 192 void CreateSessionWithNextProtos() { 193 CreateSessionWithFactory(&socket_factory_, true); 194 } 195 196 // If |use_next_protos| is true, enables SPDY and QUIC. 197 void CreateSessionWithFactory(ClientSocketFactory* socket_factory, 198 bool use_next_protos) { 199 params_.enable_quic = true; 200 params_.quic_clock = clock_; 201 params_.quic_random = &random_generator_; 202 params_.client_socket_factory = socket_factory; 203 params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_; 204 params_.host_resolver = &host_resolver_; 205 params_.cert_verifier = &cert_verifier_; 206 params_.transport_security_state = &transport_security_state_; 207 params_.proxy_service = proxy_service_.get(); 208 params_.ssl_config_service = ssl_config_service_.get(); 209 params_.http_auth_handler_factory = auth_handler_factory_.get(); 210 params_.http_server_properties = http_server_properties.GetWeakPtr(); 211 params_.quic_supported_versions = SupportedVersions(GetParam()); 212 213 if (use_next_protos) { 214 params_.use_alternate_protocols = true; 215 params_.next_protos = NextProtosSpdy3(); 216 } 217 218 session_ = new HttpNetworkSession(params_); 219 session_->quic_stream_factory()->set_require_confirmation(false); 220 } 221 222 void CheckWasQuicResponse(const scoped_ptr<HttpNetworkTransaction>& trans) { 223 const HttpResponseInfo* response = trans->GetResponseInfo(); 224 ASSERT_TRUE(response != NULL); 225 ASSERT_TRUE(response->headers.get() != NULL); 226 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 227 EXPECT_TRUE(response->was_fetched_via_spdy); 228 EXPECT_TRUE(response->was_npn_negotiated); 229 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3, 230 response->connection_info); 231 } 232 233 void CheckWasHttpResponse(const scoped_ptr<HttpNetworkTransaction>& trans) { 234 const HttpResponseInfo* response = trans->GetResponseInfo(); 235 ASSERT_TRUE(response != NULL); 236 ASSERT_TRUE(response->headers.get() != NULL); 237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 238 EXPECT_FALSE(response->was_fetched_via_spdy); 239 EXPECT_FALSE(response->was_npn_negotiated); 240 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, 241 response->connection_info); 242 } 243 244 void CheckResponseData(HttpNetworkTransaction* trans, 245 const std::string& expected) { 246 std::string response_data; 247 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); 248 EXPECT_EQ(expected, response_data); 249 } 250 251 void RunTransaction(HttpNetworkTransaction* trans) { 252 TestCompletionCallback callback; 253 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); 254 EXPECT_EQ(ERR_IO_PENDING, rv); 255 EXPECT_EQ(OK, callback.WaitForResult()); 256 } 257 258 void SendRequestAndExpectHttpResponse(const std::string& expected) { 259 scoped_ptr<HttpNetworkTransaction> trans( 260 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 261 RunTransaction(trans.get()); 262 CheckWasHttpResponse(trans); 263 CheckResponseData(trans.get(), expected); 264 } 265 266 void SendRequestAndExpectQuicResponse(const std::string& expected) { 267 scoped_ptr<HttpNetworkTransaction> trans( 268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 269 RunTransaction(trans.get()); 270 CheckWasQuicResponse(trans); 271 CheckResponseData(trans.get(), expected); 272 } 273 274 void AddQuicAlternateProtocolMapping( 275 MockCryptoClientStream::HandshakeMode handshake_mode) { 276 crypto_client_stream_factory_.set_handshake_mode(handshake_mode); 277 session_->http_server_properties()->SetAlternateProtocol( 278 HostPortPair::FromURL(request_.url), 80, QUIC); 279 } 280 281 void ExpectBrokenAlternateProtocolMapping() { 282 ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol( 283 HostPortPair::FromURL(request_.url))); 284 const PortAlternateProtocolPair alternate = 285 session_->http_server_properties()->GetAlternateProtocol( 286 HostPortPair::FromURL(request_.url)); 287 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol); 288 } 289 290 void ExpectQuicAlternateProtocolMapping() { 291 ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol( 292 HostPortPair::FromURL(request_.url))); 293 const PortAlternateProtocolPair alternate = 294 session_->http_server_properties()->GetAlternateProtocol( 295 HostPortPair::FromURL(request_.url)); 296 EXPECT_EQ(QUIC, alternate.protocol); 297 } 298 299 void AddHangingNonAlternateProtocolSocketData() { 300 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING); 301 hanging_data_.set_connect_data(hanging_connect); 302 socket_factory_.AddSocketDataProvider(&hanging_data_); 303 } 304 305 QuicTestPacketMaker maker_; 306 scoped_refptr<HttpNetworkSession> session_; 307 MockClientSocketFactory socket_factory_; 308 MockCryptoClientStreamFactory crypto_client_stream_factory_; 309 MockClock* clock_; // Owned by QuicStreamFactory after CreateSession. 310 MockHostResolver host_resolver_; 311 MockCertVerifier cert_verifier_; 312 TransportSecurityState transport_security_state_; 313 scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; 314 scoped_ptr<ProxyService> proxy_service_; 315 scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_; 316 MockRandom random_generator_; 317 HttpServerPropertiesImpl http_server_properties; 318 HttpNetworkSession::Params params_; 319 HttpRequestInfo request_; 320 CapturingBoundNetLog net_log_; 321 StaticSocketDataProvider hanging_data_; 322 }; 323 324 INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest, 325 ::testing::ValuesIn(QuicSupportedVersions())); 326 327 TEST_P(QuicNetworkTransactionTest, ForceQuic) { 328 params_.origin_to_force_quic_on = 329 HostPortPair::FromString("www.google.com:80"); 330 331 MockQuicData mock_quic_data; 332 mock_quic_data.AddWrite( 333 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 334 GetRequestHeaders("GET", "http", "/"))); 335 mock_quic_data.AddRead( 336 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 337 GetResponseHeaders("200 OK"))); 338 mock_quic_data.AddRead( 339 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 340 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 341 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 342 343 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 344 345 // The non-alternate protocol job needs to hang in order to guarantee that 346 // the alternate-protocol job will "win". 347 AddHangingNonAlternateProtocolSocketData(); 348 349 CreateSession(); 350 351 SendRequestAndExpectQuicResponse("hello!"); 352 353 // Check that the NetLog was filled reasonably. 354 net::CapturingNetLog::CapturedEntryList entries; 355 net_log_.GetEntries(&entries); 356 EXPECT_LT(0u, entries.size()); 357 358 // Check that we logged a QUIC_SESSION_PACKET_RECEIVED. 359 int pos = net::ExpectLogContainsSomewhere( 360 entries, 0, 361 net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED, 362 net::NetLog::PHASE_NONE); 363 EXPECT_LT(0, pos); 364 365 // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED. 366 pos = net::ExpectLogContainsSomewhere( 367 entries, 0, 368 net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED, 369 net::NetLog::PHASE_NONE); 370 EXPECT_LT(0, pos); 371 372 std::string packet_sequence_number; 373 ASSERT_TRUE(entries[pos].GetStringValue( 374 "packet_sequence_number", &packet_sequence_number)); 375 EXPECT_EQ("1", packet_sequence_number); 376 377 // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED. 378 pos = net::ExpectLogContainsSomewhere( 379 entries, 0, 380 net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED, 381 net::NetLog::PHASE_NONE); 382 EXPECT_LT(0, pos); 383 384 int log_stream_id; 385 ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id)); 386 EXPECT_EQ(3, log_stream_id); 387 } 388 389 TEST_P(QuicNetworkTransactionTest, QuicProxy) { 390 proxy_service_.reset( 391 ProxyService::CreateFixedFromPacResult("QUIC myproxy:70")); 392 393 MockQuicData mock_quic_data; 394 mock_quic_data.AddWrite( 395 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 396 GetRequestHeaders("GET", "http", "/"))); 397 mock_quic_data.AddRead( 398 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 399 GetResponseHeaders("200 OK"))); 400 mock_quic_data.AddRead( 401 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 402 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 403 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 404 405 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 406 407 // There is no need to set up an alternate protocol job, because 408 // no attempt will be made to speak to the proxy over TCP. 409 410 CreateSession(); 411 412 SendRequestAndExpectQuicResponse("hello!"); 413 } 414 415 TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) { 416 params_.origin_to_force_quic_on = 417 HostPortPair::FromString("www.google.com:80"); 418 419 MockQuicData mock_quic_data; 420 mock_quic_data.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED); 421 422 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0); 423 424 CreateSession(); 425 426 scoped_ptr<HttpNetworkTransaction> trans( 427 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 428 TestCompletionCallback callback; 429 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); 430 EXPECT_EQ(ERR_IO_PENDING, rv); 431 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult()); 432 } 433 434 TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) { 435 // Attempt to "force" quic on 443, which will not be honored. 436 params_.origin_to_force_quic_on = 437 HostPortPair::FromString("www.google.com:443"); 438 439 MockRead http_reads[] = { 440 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 441 MockRead("hello world"), 442 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 443 MockRead(ASYNC, OK) 444 }; 445 446 StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0); 447 socket_factory_.AddSocketDataProvider(&data); 448 SSLSocketDataProvider ssl(ASYNC, OK); 449 socket_factory_.AddSSLSocketDataProvider(&ssl); 450 451 CreateSession(); 452 453 SendRequestAndExpectHttpResponse("hello world"); 454 } 455 456 TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) { 457 MockRead http_reads[] = { 458 MockRead("HTTP/1.1 200 OK\r\n"), 459 MockRead(kQuicAlternateProtocolHttpHeader), 460 MockRead("hello world"), 461 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 462 MockRead(ASYNC, OK) 463 }; 464 465 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 466 NULL, 0); 467 socket_factory_.AddSocketDataProvider(&http_data); 468 469 MockQuicData mock_quic_data; 470 mock_quic_data.AddWrite( 471 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 472 GetRequestHeaders("GET", "http", "/"))); 473 mock_quic_data.AddRead( 474 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 475 GetResponseHeaders("200 OK"))); 476 mock_quic_data.AddRead( 477 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 478 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 479 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 480 481 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 482 483 // The non-alternate protocol job needs to hang in order to guarantee that 484 // the alternate-protocol job will "win". 485 AddHangingNonAlternateProtocolSocketData(); 486 487 CreateSessionWithNextProtos(); 488 489 SendRequestAndExpectHttpResponse("hello world"); 490 SendRequestAndExpectQuicResponse("hello!"); 491 } 492 493 TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) { 494 params_.origin_to_force_quic_on = 495 HostPortPair::FromString("www.google.com:443"); 496 params_.enable_quic_https = true; 497 498 MockRead http_reads[] = { 499 MockRead("HTTP/1.1 200 OK\r\n"), 500 MockRead(kQuicAlternateProtocolHttpsHeader), 501 MockRead("hello world"), 502 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 503 MockRead(ASYNC, OK) 504 }; 505 506 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 507 NULL, 0); 508 socket_factory_.AddSocketDataProvider(&http_data); 509 510 MockQuicData mock_quic_data; 511 mock_quic_data.AddWrite( 512 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 513 GetRequestHeaders("GET", "http", "/"))); 514 mock_quic_data.AddRead( 515 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 516 GetResponseHeaders("200 OK"))); 517 mock_quic_data.AddRead( 518 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 519 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 520 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 521 522 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 523 524 // The non-alternate protocol job needs to hang in order to guarantee that 525 // the alternate-protocol job will "win". 526 AddHangingNonAlternateProtocolSocketData(); 527 528 CreateSessionWithNextProtos(); 529 530 // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo(). 531 SendRequestAndExpectHttpResponse("hello world"); 532 } 533 534 TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) { 535 crypto_client_stream_factory_.set_handshake_mode( 536 MockCryptoClientStream::COLD_START); 537 538 MockWrite http_writes[] = { 539 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), 540 MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"), 541 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n") 542 }; 543 544 MockRead http_reads[] = { 545 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), 546 MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader), 547 MockRead(SYNCHRONOUS, 5, "hello world"), 548 MockRead(SYNCHRONOUS, OK, 6) 549 }; 550 551 DeterministicMockClientSocketFactory socket_factory; 552 553 DeterministicSocketData http_data(http_reads, arraysize(http_reads), 554 http_writes, arraysize(http_writes)); 555 socket_factory.AddSocketDataProvider(&http_data); 556 557 // The QUIC transaction will not be allowed to complete. 558 MockWrite quic_writes[] = { 559 MockWrite(ASYNC, ERR_IO_PENDING, 0) 560 }; 561 MockRead quic_reads[] = { 562 MockRead(ASYNC, ERR_IO_PENDING, 1), 563 }; 564 DeterministicSocketData quic_data(quic_reads, arraysize(quic_reads), 565 quic_writes, arraysize(quic_writes)); 566 socket_factory.AddSocketDataProvider(&quic_data); 567 568 // The HTTP transaction will complete. 569 DeterministicSocketData http_data2(http_reads, arraysize(http_reads), 570 http_writes, arraysize(http_writes)); 571 socket_factory.AddSocketDataProvider(&http_data2); 572 573 CreateSessionWithFactory(&socket_factory, true); 574 575 // Run the first request. 576 http_data.StopAfter(arraysize(http_reads) + arraysize(http_writes)); 577 SendRequestAndExpectHttpResponse("hello world"); 578 ASSERT_TRUE(http_data.at_read_eof()); 579 ASSERT_TRUE(http_data.at_write_eof()); 580 581 // Now run the second request in which the QUIC socket hangs, 582 // and verify the the transaction continues over HTTP. 583 http_data2.StopAfter(arraysize(http_reads) + arraysize(http_writes)); 584 SendRequestAndExpectHttpResponse("hello world"); 585 586 ASSERT_TRUE(http_data2.at_read_eof()); 587 ASSERT_TRUE(http_data2.at_write_eof()); 588 ASSERT_TRUE(!quic_data.at_read_eof()); 589 ASSERT_TRUE(!quic_data.at_write_eof()); 590 } 591 592 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) { 593 MockQuicData mock_quic_data; 594 mock_quic_data.AddWrite( 595 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 596 GetRequestHeaders("GET", "http", "/"))); 597 mock_quic_data.AddRead( 598 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 599 GetResponseHeaders("200 OK"))); 600 mock_quic_data.AddRead( 601 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 602 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 603 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 604 605 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 606 607 // The non-alternate protocol job needs to hang in order to guarantee that 608 // the alternate-protocol job will "win". 609 AddHangingNonAlternateProtocolSocketData(); 610 611 CreateSessionWithNextProtos(); 612 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 613 SendRequestAndExpectQuicResponse("hello!"); 614 } 615 616 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) { 617 MockQuicData mock_quic_data; 618 mock_quic_data.AddWrite( 619 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 620 GetRequestHeaders("GET", "http", "/"))); 621 mock_quic_data.AddRead( 622 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 623 GetResponseHeaders("200 OK"))); 624 mock_quic_data.AddRead( 625 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 626 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 627 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 628 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 629 630 // In order for a new QUIC session to be established via alternate-protocol 631 // without racing an HTTP connection, we need the host resolution to happen 632 // synchronously. 633 host_resolver_.set_synchronous_mode(true); 634 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); 635 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); 636 AddressList address; 637 host_resolver_.Resolve(info, 638 DEFAULT_PRIORITY, 639 &address, 640 CompletionCallback(), 641 NULL, 642 net_log_.bound()); 643 644 CreateSessionWithNextProtos(); 645 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 646 SendRequestAndExpectQuicResponse("hello!"); 647 } 648 649 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) { 650 proxy_service_.reset( 651 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 652 653 // Since we are using a proxy, the QUIC job will not succeed. 654 MockWrite http_writes[] = { 655 MockWrite(SYNCHRONOUS, 0, "GET http://www.google.com/ HTTP/1.1\r\n"), 656 MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"), 657 MockWrite(SYNCHRONOUS, 2, "Proxy-Connection: keep-alive\r\n\r\n") 658 }; 659 660 MockRead http_reads[] = { 661 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), 662 MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader), 663 MockRead(SYNCHRONOUS, 5, "hello world"), 664 MockRead(SYNCHRONOUS, OK, 6) 665 }; 666 667 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 668 http_writes, arraysize(http_writes)); 669 socket_factory_.AddSocketDataProvider(&http_data); 670 671 // In order for a new QUIC session to be established via alternate-protocol 672 // without racing an HTTP connection, we need the host resolution to happen 673 // synchronously. 674 host_resolver_.set_synchronous_mode(true); 675 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); 676 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); 677 AddressList address; 678 host_resolver_.Resolve(info, 679 DEFAULT_PRIORITY, 680 &address, 681 CompletionCallback(), 682 NULL, 683 net_log_.bound()); 684 685 CreateSessionWithNextProtos(); 686 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 687 SendRequestAndExpectHttpResponse("hello world"); 688 } 689 690 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) { 691 MockQuicData mock_quic_data; 692 mock_quic_data.AddWrite( 693 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 694 GetRequestHeaders("GET", "http", "/"))); 695 mock_quic_data.AddRead( 696 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, 697 GetResponseHeaders("200 OK"))); 698 mock_quic_data.AddRead( 699 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); 700 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 701 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF 702 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); 703 704 // The non-alternate protocol job needs to hang in order to guarantee that 705 // the alternate-protocol job will "win". 706 AddHangingNonAlternateProtocolSocketData(); 707 708 // In order for a new QUIC session to be established via alternate-protocol 709 // without racing an HTTP connection, we need the host resolution to happen 710 // synchronously. Of course, even though QUIC *could* perform a 0-RTT 711 // connection to the the server, in this test we require confirmation 712 // before encrypting so the HTTP job will still start. 713 host_resolver_.set_synchronous_mode(true); 714 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); 715 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); 716 AddressList address; 717 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, 718 CompletionCallback(), NULL, net_log_.bound()); 719 720 CreateSessionWithNextProtos(); 721 session_->quic_stream_factory()->set_require_confirmation(true); 722 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 723 724 scoped_ptr<HttpNetworkTransaction> trans( 725 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 726 TestCompletionCallback callback; 727 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); 728 EXPECT_EQ(ERR_IO_PENDING, rv); 729 730 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( 731 QuicSession::HANDSHAKE_CONFIRMED); 732 EXPECT_EQ(OK, callback.WaitForResult()); 733 } 734 735 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) { 736 // Alternate-protocol job 737 scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1)); 738 MockRead quic_reads[] = { 739 MockRead(ASYNC, close->data(), close->length()), 740 MockRead(ASYNC, OK), // EOF 741 }; 742 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), 743 NULL, 0); 744 socket_factory_.AddSocketDataProvider(&quic_data); 745 746 // Main job which will succeed even though the alternate job fails. 747 MockRead http_reads[] = { 748 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 749 MockRead("hello from http"), 750 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 751 MockRead(ASYNC, OK) 752 }; 753 754 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 755 NULL, 0); 756 socket_factory_.AddSocketDataProvider(&http_data); 757 758 CreateSessionWithNextProtos(); 759 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); 760 SendRequestAndExpectHttpResponse("hello from http"); 761 ExpectBrokenAlternateProtocolMapping(); 762 } 763 764 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) { 765 // Alternate-protocol job 766 MockRead quic_reads[] = { 767 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), 768 }; 769 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), 770 NULL, 0); 771 socket_factory_.AddSocketDataProvider(&quic_data); 772 773 // Main job which will succeed even though the alternate job fails. 774 MockRead http_reads[] = { 775 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 776 MockRead("hello from http"), 777 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 778 MockRead(ASYNC, OK) 779 }; 780 781 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 782 NULL, 0); 783 socket_factory_.AddSocketDataProvider(&http_data); 784 785 CreateSessionWithNextProtos(); 786 787 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); 788 SendRequestAndExpectHttpResponse("hello from http"); 789 ExpectBrokenAlternateProtocolMapping(); 790 } 791 792 TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) { 793 // Alternate-protocol job will fail when the session attempts to read. 794 MockRead quic_reads[] = { 795 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), 796 }; 797 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), 798 NULL, 0); 799 socket_factory_.AddSocketDataProvider(&quic_data); 800 801 // Main job will also fail. 802 MockRead http_reads[] = { 803 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), 804 }; 805 806 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 807 NULL, 0); 808 http_data.set_connect_data(MockConnect(ASYNC, ERR_SOCKET_NOT_CONNECTED)); 809 socket_factory_.AddSocketDataProvider(&http_data); 810 811 CreateSessionWithNextProtos(); 812 813 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); 814 scoped_ptr<HttpNetworkTransaction> trans( 815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 816 TestCompletionCallback callback; 817 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); 818 EXPECT_EQ(ERR_IO_PENDING, rv); 819 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult()); 820 ExpectQuicAlternateProtocolMapping(); 821 } 822 823 TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) { 824 // Alternate-protocol job 825 MockRead quic_reads[] = { 826 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), 827 }; 828 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), 829 NULL, 0); 830 socket_factory_.AddSocketDataProvider(&quic_data); 831 832 AddHangingNonAlternateProtocolSocketData(); 833 834 // Second Alternate-protocol job which will race with the TCP job. 835 StaticSocketDataProvider quic_data2(quic_reads, arraysize(quic_reads), 836 NULL, 0); 837 socket_factory_.AddSocketDataProvider(&quic_data2); 838 839 // Final job that will proceed when the QUIC job fails. 840 MockRead http_reads[] = { 841 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 842 MockRead("hello from http"), 843 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 844 MockRead(ASYNC, OK) 845 }; 846 847 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 848 NULL, 0); 849 socket_factory_.AddSocketDataProvider(&http_data); 850 851 CreateSessionWithNextProtos(); 852 853 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 854 855 SendRequestAndExpectHttpResponse("hello from http"); 856 857 ExpectBrokenAlternateProtocolMapping(); 858 859 EXPECT_TRUE(quic_data.at_read_eof()); 860 EXPECT_TRUE(quic_data.at_write_eof()); 861 } 862 863 TEST_P(QuicNetworkTransactionTest, DISABLED_HangingZeroRttFallback) { 864 // Alternate-protocol job 865 MockRead quic_reads[] = { 866 MockRead(ASYNC, ERR_IO_PENDING), 867 }; 868 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), 869 NULL, 0); 870 socket_factory_.AddSocketDataProvider(&quic_data); 871 872 // Main job that will proceed when the QUIC job fails. 873 MockRead http_reads[] = { 874 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 875 MockRead("hello from http"), 876 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 877 MockRead(ASYNC, OK) 878 }; 879 880 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 881 NULL, 0); 882 socket_factory_.AddSocketDataProvider(&http_data); 883 884 CreateSessionWithNextProtos(); 885 886 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 887 888 SendRequestAndExpectHttpResponse("hello from http"); 889 } 890 891 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) { 892 // Alternate-protocol job will fail before creating a QUIC session. 893 StaticSocketDataProvider quic_data(NULL, 0, NULL, 0); 894 quic_data.set_connect_data(MockConnect(SYNCHRONOUS, 895 ERR_INTERNET_DISCONNECTED)); 896 socket_factory_.AddSocketDataProvider(&quic_data); 897 898 // Main job which will succeed even though the alternate job fails. 899 MockRead http_reads[] = { 900 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 901 MockRead("hello from http"), 902 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 903 MockRead(ASYNC, OK) 904 }; 905 906 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 907 NULL, 0); 908 socket_factory_.AddSocketDataProvider(&http_data); 909 910 CreateSessionWithNextProtos(); 911 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); 912 SendRequestAndExpectHttpResponse("hello from http"); 913 914 ExpectBrokenAlternateProtocolMapping(); 915 } 916 917 TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) { 918 MockQuicData mock_quic_data; 919 mock_quic_data.AddRead(ConstructConnectionClosePacket(1)); 920 mock_quic_data.AddWrite( 921 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, 922 GetRequestHeaders("GET", "http", "/"))); 923 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); 924 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0); 925 926 // When the QUIC connection fails, we will try the request again over HTTP. 927 MockRead http_reads[] = { 928 MockRead("HTTP/1.1 200 OK\r\n"), 929 MockRead(kQuicAlternateProtocolHttpHeader), 930 MockRead("hello world"), 931 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 932 MockRead(ASYNC, OK) 933 }; 934 935 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 936 NULL, 0); 937 socket_factory_.AddSocketDataProvider(&http_data); 938 939 // In order for a new QUIC session to be established via alternate-protocol 940 // without racing an HTTP connection, we need the host resolution to happen 941 // synchronously. 942 host_resolver_.set_synchronous_mode(true); 943 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); 944 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); 945 AddressList address; 946 host_resolver_.Resolve(info, 947 DEFAULT_PRIORITY, 948 &address, 949 CompletionCallback(), 950 NULL, 951 net_log_.bound()); 952 953 CreateSessionWithNextProtos(); 954 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); 955 SendRequestAndExpectHttpResponse("hello world"); 956 } 957 958 } // namespace test 959 } // namespace net 960