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