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 "net/quic/quic_http_stream.h" 6 7 #include <vector> 8 9 #include "net/base/net_errors.h" 10 #include "net/base/test_completion_callback.h" 11 #include "net/base/upload_bytes_element_reader.h" 12 #include "net/base/upload_data_stream.h" 13 #include "net/http/http_response_headers.h" 14 #include "net/quic/congestion_control/receive_algorithm_interface.h" 15 #include "net/quic/congestion_control/send_algorithm_interface.h" 16 #include "net/quic/crypto/crypto_protocol.h" 17 #include "net/quic/crypto/quic_decrypter.h" 18 #include "net/quic/crypto/quic_encrypter.h" 19 #include "net/quic/quic_client_session.h" 20 #include "net/quic/quic_connection.h" 21 #include "net/quic/quic_connection_helper.h" 22 #include "net/quic/test_tools/mock_clock.h" 23 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h" 24 #include "net/quic/test_tools/mock_random.h" 25 #include "net/quic/test_tools/quic_connection_peer.h" 26 #include "net/quic/test_tools/quic_test_utils.h" 27 #include "net/quic/test_tools/test_task_runner.h" 28 #include "net/socket/socket_test_util.h" 29 #include "net/spdy/spdy_frame_builder.h" 30 #include "net/spdy/spdy_framer.h" 31 #include "net/spdy/spdy_http_utils.h" 32 #include "net/spdy/spdy_protocol.h" 33 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gtest/include/gtest/gtest.h" 35 36 using testing::_; 37 38 namespace net { 39 namespace test { 40 namespace { 41 42 const char kUploadData[] = "hello world!"; 43 44 class TestQuicConnection : public QuicConnection { 45 public: 46 TestQuicConnection(QuicGuid guid, 47 IPEndPoint address, 48 QuicConnectionHelper* helper) 49 : QuicConnection(guid, address, helper, false, QuicVersionMax()) { 50 } 51 52 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) { 53 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm); 54 } 55 56 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) { 57 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm); 58 } 59 }; 60 61 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface { 62 public: 63 explicit TestReceiveAlgorithm(QuicCongestionFeedbackFrame* feedback) 64 : feedback_(feedback) { 65 } 66 67 bool GenerateCongestionFeedback( 68 QuicCongestionFeedbackFrame* congestion_feedback) { 69 if (feedback_ == NULL) { 70 return false; 71 } 72 *congestion_feedback = *feedback_; 73 return true; 74 } 75 76 MOCK_METHOD4(RecordIncomingPacket, 77 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime, bool)); 78 79 private: 80 MockClock clock_; 81 QuicCongestionFeedbackFrame* feedback_; 82 83 DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm); 84 }; 85 86 // Subclass of QuicHttpStream that closes itself when the first piece of data 87 // is received. 88 class AutoClosingStream : public QuicHttpStream { 89 public: 90 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session) 91 : QuicHttpStream(session) { 92 } 93 94 virtual int OnDataReceived(const char* data, int length) OVERRIDE { 95 Close(false); 96 return OK; 97 } 98 }; 99 100 } // namespace 101 102 class QuicHttpStreamTest : public ::testing::TestWithParam<bool> { 103 protected: 104 const static bool kFin = true; 105 // Holds a packet to be written to the wire, and the IO mode that should 106 // be used by the mock socket when performing the write. 107 struct PacketToWrite { 108 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet) 109 : mode(mode), 110 packet(packet) { 111 } 112 IoMode mode; 113 QuicEncryptedPacket* packet; 114 }; 115 116 QuicHttpStreamTest() 117 : net_log_(BoundNetLog()), 118 use_closing_stream_(false), 119 read_buffer_(new IOBufferWithSize(4096)), 120 guid_(2), 121 framer_(QuicVersionMax(), QuicTime::Zero(), false), 122 creator_(guid_, &framer_, &random_, false) { 123 IPAddressNumber ip; 124 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip)); 125 peer_addr_ = IPEndPoint(ip, 443); 126 self_addr_ = IPEndPoint(ip, 8435); 127 } 128 129 ~QuicHttpStreamTest() { 130 for (size_t i = 0; i < writes_.size(); i++) { 131 delete writes_[i].packet; 132 } 133 } 134 135 // Adds a packet to the list of expected writes. 136 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) { 137 writes_.push_back(PacketToWrite(mode, packet)); 138 } 139 140 // Returns the packet to be written at position |pos|. 141 QuicEncryptedPacket* GetWrite(size_t pos) { 142 return writes_[pos].packet; 143 } 144 145 bool AtEof() { 146 return socket_data_->at_read_eof() && socket_data_->at_write_eof(); 147 } 148 149 void ProcessPacket(const QuicEncryptedPacket& packet) { 150 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet); 151 } 152 153 // Configures the test fixture to use the list of expected writes. 154 void Initialize() { 155 mock_writes_.reset(new MockWrite[writes_.size()]); 156 for (size_t i = 0; i < writes_.size(); i++) { 157 mock_writes_[i] = MockWrite(writes_[i].mode, 158 writes_[i].packet->data(), 159 writes_[i].packet->length()); 160 }; 161 162 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(), 163 writes_.size())); 164 165 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(), 166 net_log_.net_log()); 167 socket->Connect(peer_addr_); 168 runner_ = new TestTaskRunner(&clock_); 169 send_algorithm_ = new MockSendAlgorithm(); 170 receive_algorithm_ = new TestReceiveAlgorithm(NULL); 171 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly( 172 testing::Return(QuicTime::Delta::Zero())); 173 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)). 174 WillRepeatedly(testing::Return(QuicTime::Delta::Zero())); 175 helper_ = new QuicConnectionHelper(runner_.get(), &clock_, 176 &random_generator_, socket); 177 connection_ = new TestQuicConnection(guid_, peer_addr_, helper_); 178 connection_->set_visitor(&visitor_); 179 connection_->SetSendAlgorithm(send_algorithm_); 180 connection_->SetReceiveAlgorithm(receive_algorithm_); 181 crypto_config_.SetDefaults(); 182 session_.reset(new QuicClientSession(connection_, socket, NULL, 183 &crypto_client_stream_factory_, 184 "www.google.com", DefaultQuicConfig(), 185 &crypto_config_, NULL)); 186 session_->GetCryptoStream()->CryptoConnect(); 187 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed()); 188 stream_.reset(use_closing_stream_ ? 189 new AutoClosingStream(session_->GetWeakPtr()) : 190 new QuicHttpStream(session_->GetWeakPtr())); 191 } 192 193 void SetRequestString(const std::string& method, const std::string& path) { 194 SpdyHeaderBlock headers; 195 headers[":method"] = method; 196 headers[":host"] = "www.google.com"; 197 headers[":path"] = path; 198 headers[":scheme"] = "http"; 199 headers[":version"] = "HTTP/1.1"; 200 request_data_ = SerializeHeaderBlock(headers); 201 } 202 203 void SetResponseString(const std::string& status, const std::string& body) { 204 SpdyHeaderBlock headers; 205 headers[":status"] = status; 206 headers[":version"] = "HTTP/1.1"; 207 headers["content-type"] = "text/plain"; 208 response_data_ = SerializeHeaderBlock(headers) + body; 209 } 210 211 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) { 212 QuicSpdyCompressor compressor; 213 return compressor.CompressHeaders(headers); 214 } 215 216 // Returns a newly created packet to send kData on stream 1. 217 QuicEncryptedPacket* ConstructDataPacket( 218 QuicPacketSequenceNumber sequence_number, 219 bool should_include_version, 220 bool fin, 221 QuicStreamOffset offset, 222 base::StringPiece data) { 223 InitializeHeader(sequence_number, should_include_version); 224 QuicStreamFrame frame(3, fin, offset, data); 225 return ConstructPacket(header_, QuicFrame(&frame)); 226 } 227 228 // Returns a newly created packet to send ack data. 229 QuicEncryptedPacket* ConstructAckPacket( 230 QuicPacketSequenceNumber sequence_number, 231 QuicPacketSequenceNumber largest_received, 232 QuicPacketSequenceNumber least_unacked) { 233 InitializeHeader(sequence_number, false); 234 235 QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked); 236 ack.sent_info.entropy_hash = 0; 237 ack.received_info.entropy_hash = 0; 238 239 return ConstructPacket(header_, QuicFrame(&ack)); 240 } 241 242 // Returns a newly created packet to send ack data. 243 QuicEncryptedPacket* ConstructRstPacket( 244 QuicPacketSequenceNumber sequence_number, 245 QuicStreamId stream_id) { 246 InitializeHeader(sequence_number, false); 247 248 QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR); 249 return ConstructPacket(header_, QuicFrame(&rst)); 250 } 251 252 BoundNetLog net_log_; 253 bool use_closing_stream_; 254 MockSendAlgorithm* send_algorithm_; 255 TestReceiveAlgorithm* receive_algorithm_; 256 scoped_refptr<TestTaskRunner> runner_; 257 scoped_ptr<MockWrite[]> mock_writes_; 258 MockClock clock_; 259 MockRandom random_generator_; 260 TestQuicConnection* connection_; 261 QuicConnectionHelper* helper_; 262 testing::StrictMock<MockConnectionVisitor> visitor_; 263 scoped_ptr<QuicHttpStream> stream_; 264 scoped_ptr<QuicClientSession> session_; 265 QuicCryptoClientConfig crypto_config_; 266 TestCompletionCallback callback_; 267 HttpRequestInfo request_; 268 HttpRequestHeaders headers_; 269 HttpResponseInfo response_; 270 scoped_refptr<IOBufferWithSize> read_buffer_; 271 std::string request_data_; 272 std::string response_data_; 273 274 private: 275 void InitializeHeader(QuicPacketSequenceNumber sequence_number, 276 bool should_include_version) { 277 header_.public_header.guid = guid_; 278 header_.public_header.reset_flag = false; 279 header_.public_header.version_flag = should_include_version; 280 header_.packet_sequence_number = sequence_number; 281 header_.fec_group = 0; 282 header_.entropy_flag = false; 283 header_.fec_flag = false; 284 } 285 286 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header, 287 const QuicFrame& frame) { 288 QuicFrames frames; 289 frames.push_back(frame); 290 scoped_ptr<QuicPacket> packet( 291 framer_.BuildUnsizedDataPacket(header_, frames).packet); 292 return framer_.EncryptPacket( 293 ENCRYPTION_NONE, header.packet_sequence_number, *packet); 294 } 295 296 const QuicGuid guid_; 297 QuicFramer framer_; 298 IPEndPoint self_addr_; 299 IPEndPoint peer_addr_; 300 MockRandom random_; 301 MockCryptoClientStreamFactory crypto_client_stream_factory_; 302 QuicPacketCreator creator_; 303 QuicPacketHeader header_; 304 scoped_ptr<StaticSocketDataProvider> socket_data_; 305 std::vector<PacketToWrite> writes_; 306 }; 307 308 TEST_F(QuicHttpStreamTest, RenewStreamForAuth) { 309 Initialize(); 310 EXPECT_EQ(NULL, stream_->RenewStreamForAuth()); 311 } 312 313 TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) { 314 Initialize(); 315 EXPECT_TRUE(stream_->CanFindEndOfResponse()); 316 } 317 318 TEST_F(QuicHttpStreamTest, IsConnectionReusable) { 319 Initialize(); 320 EXPECT_FALSE(stream_->IsConnectionReusable()); 321 } 322 323 TEST_F(QuicHttpStreamTest, GetRequest) { 324 SetRequestString("GET", "/"); 325 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, 326 request_data_)); 327 Initialize(); 328 329 request_.method = "GET"; 330 request_.url = GURL("http://www.google.com/"); 331 332 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 333 net_log_, callback_.callback())); 334 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 335 callback_.callback())); 336 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 337 338 // Ack the request. 339 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0)); 340 ProcessPacket(*ack); 341 342 EXPECT_EQ(ERR_IO_PENDING, 343 stream_->ReadResponseHeaders(callback_.callback())); 344 345 // Send the response without a body. 346 SetResponseString("404 Not Found", std::string()); 347 scoped_ptr<QuicEncryptedPacket> resp( 348 ConstructDataPacket(2, false, kFin, 0, response_data_)); 349 ProcessPacket(*resp); 350 351 // Now that the headers have been processed, the callback will return. 352 EXPECT_EQ(OK, callback_.WaitForResult()); 353 ASSERT_TRUE(response_.headers.get()); 354 EXPECT_EQ(404, response_.headers->response_code()); 355 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 356 357 // There is no body, so this should return immediately. 358 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(), 359 read_buffer_->size(), 360 callback_.callback())); 361 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 362 EXPECT_TRUE(AtEof()); 363 } 364 365 TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) { 366 SetRequestString("GET", "/"); 367 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_)); 368 Initialize(); 369 370 request_.method = "GET"; 371 request_.url = GURL("http://www.google.com/"); 372 373 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 374 net_log_, callback_.callback())); 375 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 376 callback_.callback())); 377 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 378 379 // Ack the request. 380 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0)); 381 ProcessPacket(*ack); 382 383 EXPECT_EQ(ERR_IO_PENDING, 384 stream_->ReadResponseHeaders(callback_.callback())); 385 386 // Send the response with a body. 387 SetResponseString("200 OK", "hello world!"); 388 scoped_ptr<QuicEncryptedPacket> resp( 389 ConstructDataPacket(2, false, kFin, 0, response_data_)); 390 ProcessPacket(*resp); 391 392 // Now that the headers have been processed, the callback will return. 393 EXPECT_EQ(OK, callback_.WaitForResult()); 394 ASSERT_TRUE(response_.headers.get()); 395 EXPECT_EQ(200, response_.headers->response_code()); 396 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 397 398 // There is no body, so this should return immediately. 399 // Since the body has already arrived, this should return immediately. 400 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(), 401 read_buffer_->size(), 402 callback_.callback())); 403 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 404 EXPECT_TRUE(AtEof()); 405 } 406 407 TEST_F(QuicHttpStreamTest, SendPostRequest) { 408 SetRequestString("POST", "/"); 409 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_)); 410 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin, 411 request_data_.length(), 412 kUploadData)); 413 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 3, 1)); 414 415 Initialize(); 416 417 ScopedVector<UploadElementReader> element_readers; 418 element_readers.push_back( 419 new UploadBytesElementReader(kUploadData, strlen(kUploadData))); 420 UploadDataStream upload_data_stream(&element_readers, 0); 421 request_.method = "POST"; 422 request_.url = GURL("http://www.google.com/"); 423 request_.upload_data_stream = &upload_data_stream; 424 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); 425 426 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 427 net_log_, callback_.callback())); 428 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 429 callback_.callback())); 430 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 431 432 // Ack both packets in the request. 433 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0)); 434 ProcessPacket(*ack); 435 436 // Send the response headers (but not the body). 437 SetResponseString("200 OK", std::string()); 438 scoped_ptr<QuicEncryptedPacket> resp( 439 ConstructDataPacket(2, false, !kFin, 0, response_data_)); 440 ProcessPacket(*resp); 441 442 // Since the headers have already arrived, this should return immediately. 443 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback())); 444 ASSERT_TRUE(response_.headers.get()); 445 EXPECT_EQ(200, response_.headers->response_code()); 446 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 447 448 // Send the response body. 449 const char kResponseBody[] = "Hello world!"; 450 scoped_ptr<QuicEncryptedPacket> resp_body( 451 ConstructDataPacket(3, false, kFin, response_data_.length(), 452 kResponseBody)); 453 ProcessPacket(*resp_body); 454 455 // Since the body has already arrived, this should return immediately. 456 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), 457 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(), 458 callback_.callback())); 459 460 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 461 EXPECT_TRUE(AtEof()); 462 } 463 464 TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) { 465 SetRequestString("POST", "/"); 466 size_t chunk_size = strlen(kUploadData); 467 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, !kFin, 0, request_data_)); 468 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, !kFin, 469 request_data_.length(), 470 kUploadData)); 471 AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin, 472 request_data_.length() + chunk_size, 473 kUploadData)); 474 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 1)); 475 476 Initialize(); 477 478 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); 479 upload_data_stream.AppendChunk(kUploadData, chunk_size, false); 480 481 request_.method = "POST"; 482 request_.url = GURL("http://www.google.com/"); 483 request_.upload_data_stream = &upload_data_stream; 484 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); 485 486 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 487 net_log_, callback_.callback())); 488 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, 489 callback_.callback())); 490 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 491 492 upload_data_stream.AppendChunk(kUploadData, chunk_size, true); 493 494 // Ack both packets in the request. 495 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0)); 496 ProcessPacket(*ack); 497 498 // Send the response headers (but not the body). 499 SetResponseString("200 OK", std::string()); 500 scoped_ptr<QuicEncryptedPacket> resp( 501 ConstructDataPacket(2, false, !kFin, 0, response_data_)); 502 ProcessPacket(*resp); 503 504 // Since the headers have already arrived, this should return immediately. 505 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback())); 506 ASSERT_TRUE(response_.headers.get()); 507 EXPECT_EQ(200, response_.headers->response_code()); 508 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 509 510 // Send the response body. 511 const char kResponseBody[] = "Hello world!"; 512 scoped_ptr<QuicEncryptedPacket> resp_body( 513 ConstructDataPacket(3, false, kFin, response_data_.length(), 514 kResponseBody)); 515 ProcessPacket(*resp_body); 516 517 // Since the body has already arrived, this should return immediately. 518 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)), 519 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(), 520 callback_.callback())); 521 522 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 523 EXPECT_TRUE(AtEof()); 524 } 525 526 TEST_F(QuicHttpStreamTest, DestroyedEarly) { 527 SetRequestString("GET", "/"); 528 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_)); 529 use_closing_stream_ = true; 530 Initialize(); 531 532 request_.method = "GET"; 533 request_.url = GURL("http://www.google.com/"); 534 535 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 536 net_log_, callback_.callback())); 537 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 538 callback_.callback())); 539 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 540 541 // Ack the request. 542 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0, 0)); 543 ProcessPacket(*ack); 544 EXPECT_EQ(ERR_IO_PENDING, 545 stream_->ReadResponseHeaders(callback_.callback())); 546 547 // Send the response with a body. 548 SetResponseString("404 OK", "hello world!"); 549 scoped_ptr<QuicEncryptedPacket> resp( 550 ConstructDataPacket(2, false, kFin, 0, response_data_)); 551 552 // In the course of processing this packet, the QuicHttpStream close itself. 553 ProcessPacket(*resp); 554 555 EXPECT_TRUE(AtEof()); 556 } 557 558 } // namespace test 559 560 } // namespace net 561