Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: net/socket/ssl_client_socket_unittest.cc

Issue 208293002: Add False Start tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add negative tests Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/ssl_client_socket.h" 5 #include "net/socket/ssl_client_socket.h"
6 6
7 #include "base/callback_helpers.h" 7 #include "base/callback_helpers.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/run_loop.h"
9 #include "net/base/address_list.h" 10 #include "net/base/address_list.h"
10 #include "net/base/io_buffer.h" 11 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h" 12 #include "net/base/net_errors.h"
12 #include "net/base/net_log.h" 13 #include "net/base/net_log.h"
13 #include "net/base/net_log_unittest.h" 14 #include "net/base/net_log_unittest.h"
14 #include "net/base/test_completion_callback.h" 15 #include "net/base/test_completion_callback.h"
15 #include "net/base/test_data_directory.h" 16 #include "net/base/test_data_directory.h"
16 #include "net/cert/mock_cert_verifier.h" 17 #include "net/cert/mock_cert_verifier.h"
17 #include "net/cert/test_root_certs.h" 18 #include "net/cert/test_root_certs.h"
18 #include "net/dns/host_resolver.h" 19 #include "net/dns/host_resolver.h"
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // deterministic manner (e.g.: independent of the TestServer and the OS's 321 // deterministic manner (e.g.: independent of the TestServer and the OS's
321 // semantics). 322 // semantics).
322 class FakeBlockingStreamSocket : public WrappedStreamSocket { 323 class FakeBlockingStreamSocket : public WrappedStreamSocket {
323 public: 324 public:
324 explicit FakeBlockingStreamSocket(scoped_ptr<StreamSocket> transport); 325 explicit FakeBlockingStreamSocket(scoped_ptr<StreamSocket> transport);
325 virtual ~FakeBlockingStreamSocket() {} 326 virtual ~FakeBlockingStreamSocket() {}
326 327
327 // Socket implementation: 328 // Socket implementation:
328 virtual int Read(IOBuffer* buf, 329 virtual int Read(IOBuffer* buf,
329 int buf_len, 330 int buf_len,
330 const CompletionCallback& callback) OVERRIDE { 331 const CompletionCallback& callback) OVERRIDE;
331 return read_state_.RunWrappedFunction(buf, buf_len, callback);
332 }
333 virtual int Write(IOBuffer* buf, 332 virtual int Write(IOBuffer* buf,
334 int buf_len, 333 int buf_len,
335 const CompletionCallback& callback) OVERRIDE { 334 const CompletionCallback& callback) OVERRIDE;
336 return write_state_.RunWrappedFunction(buf, buf_len, callback);
337 }
338 335
339 // Causes the next call to Read() to return ERR_IO_PENDING, not completing 336 // Causes the next call to Read() to return ERR_IO_PENDING, not completing
340 // (invoking the callback) until UnblockRead() has been called and the 337 // (invoking the callback) until UnblockRead() has been called and the
341 // underlying transport has completed. 338 // underlying transport has completed.
342 void SetNextReadShouldBlock() { read_state_.SetShouldBlock(); } 339 void SetNextReadShouldBlock();
343 void UnblockRead() { read_state_.Unblock(); } 340 void UnblockRead();
344 341
345 // Causes the next call to Write() to return ERR_IO_PENDING, not completing 342 // Waits for the blocked Read() call to be complete at the underlying
346 // (invoking the callback) until UnblockWrite() has been called and the 343 // transport.
347 // underlying transport has completed. 344 void WaitForRead();
Ryan Sleevi 2014/03/31 20:47:55 Red flag: "WaitFor"* anything, with a RunLoop, is
348 void SetNextWriteShouldBlock() { write_state_.SetShouldBlock(); } 345
349 void UnblockWrite() { write_state_.Unblock(); } 346 // Causes the next call to Write() to return ERR_IO_PENDING, not beginning the
347 // underlying transport until UnblockWrite() has been called.
348 void SetNextWriteShouldBlock();
349 void UnblockWrite();
350
351 // Waits for the blocked Write() call to be scheduled.
352 void WaitForWrite();
350 353
351 private: 354 private:
352 // Tracks the state for simulating a blocking Read/Write operation. 355 // Handles completion from the underlying transport read.
353 class BlockingState { 356 void OnReadCompleted(int result);
354 public:
355 // Wrapper for the underlying Socket function to call (ie: Read/Write).
356 typedef base::Callback<int(IOBuffer*, int, const CompletionCallback&)>
357 WrappedSocketFunction;
358 357
359 explicit BlockingState(const WrappedSocketFunction& function); 358 // True if read callbacks are blocked.
360 ~BlockingState() {} 359 bool should_block_read_;
361 360
362 // Sets the next call to RunWrappedFunction() to block, returning 361 // The user callback for the pending read call.
363 // ERR_IO_PENDING and not invoking the user callback until Unblock() is 362 CompletionCallback pending_read_callback_;
364 // called.
365 void SetShouldBlock();
366 363
367 // Unblocks the currently blocked pending function, invoking the user 364 // The result for the blocked read callback, or ERR_IO_PENDING if not
368 // callback if the results are immediately available. 365 // completed.
369 // Note: It's not valid to call this unless SetShouldBlock() has been 366 int pending_read_result_;
370 // called beforehand.
371 void Unblock();
372 367
373 // Performs the wrapped socket function on the underlying transport. If 368 // WaitForRead() wait loop.
374 // configured to block via SetShouldBlock(), then |user_callback| will not 369 scoped_ptr<base::RunLoop> read_loop_;
375 // be invoked until Unblock() has been called.
376 int RunWrappedFunction(IOBuffer* buf,
377 int len,
378 const CompletionCallback& user_callback);
379 370
380 private: 371 // True if write calls are blocked.
381 // Handles completion from the underlying wrapped socket function. 372 bool should_block_write_;
382 void OnCompleted(int result);
383 373
384 WrappedSocketFunction wrapped_function_; 374 // The buffer for the pending write, or NULL if not scheduled.
385 bool should_block_; 375 scoped_refptr<IOBuffer> pending_write_buf_;
386 bool have_result_;
387 int pending_result_;
388 CompletionCallback user_callback_;
389 };
390 376
391 BlockingState read_state_; 377 // The callback for the pending write call.
392 BlockingState write_state_; 378 CompletionCallback pending_write_callback_;
393 379
394 DISALLOW_COPY_AND_ASSIGN(FakeBlockingStreamSocket); 380 // The length for the pending write, or -1 if not scheduled.
381 int pending_write_len_;
382
383 // WaitForWrite() wait loop.
384 scoped_ptr<base::RunLoop> write_loop_;
395 }; 385 };
396 386
397 FakeBlockingStreamSocket::FakeBlockingStreamSocket( 387 FakeBlockingStreamSocket::FakeBlockingStreamSocket(
398 scoped_ptr<StreamSocket> transport) 388 scoped_ptr<StreamSocket> transport)
399 : WrappedStreamSocket(transport.Pass()), 389 : WrappedStreamSocket(transport.Pass()),
400 read_state_(base::Bind(&Socket::Read, 390 should_block_read_(false),
401 base::Unretained(transport_.get()))), 391 pending_read_result_(ERR_IO_PENDING),
402 write_state_(base::Bind(&Socket::Write, 392 should_block_write_(false),
403 base::Unretained(transport_.get()))) {} 393 pending_write_len_(-1) {}
404 394
405 FakeBlockingStreamSocket::BlockingState::BlockingState( 395 int FakeBlockingStreamSocket::Read(IOBuffer* buf,
406 const WrappedSocketFunction& function) 396 int len,
407 : wrapped_function_(function), 397 const CompletionCallback& callback) {
408 should_block_(false), 398 if (!should_block_read_)
409 have_result_(false), 399 return transport_->Read(buf, len, callback);
410 pending_result_(OK) {}
411 400
412 void FakeBlockingStreamSocket::BlockingState::SetShouldBlock() { 401 DCHECK(pending_read_callback_.is_null());
413 DCHECK(!should_block_); 402 DCHECK_EQ(ERR_IO_PENDING, pending_read_result_);
414 should_block_ = true; 403
404 int rv = transport_->Read(buf, len, base::Bind(
405 &FakeBlockingStreamSocket::OnReadCompleted, base::Unretained(this)));
406 if (rv == ERR_IO_PENDING) {
407 pending_read_callback_ = callback;
408 } else {
409 OnReadCompleted(rv);
410 }
411 return ERR_IO_PENDING;
415 } 412 }
416 413
417 void FakeBlockingStreamSocket::BlockingState::Unblock() { 414 int FakeBlockingStreamSocket::Write(IOBuffer* buf,
418 DCHECK(should_block_); 415 int len,
419 should_block_ = false; 416 const CompletionCallback& callback) {
417 DCHECK(buf);
418 DCHECK_LE(0, len);
419
420 if (!should_block_write_)
421 return transport_->Write(buf, len, callback);
422
423 // Schedule the write, but do nothing.
424 DCHECK(!pending_write_buf_);
425 DCHECK_EQ(-1, pending_write_len_);
426 DCHECK(pending_write_callback_.is_null());
427 pending_write_buf_ = buf;
428 pending_write_len_ = len;
429 pending_write_callback_ = callback;
430
431 // Stop the write loop, if any.
432 if (write_loop_)
433 write_loop_->Quit();
434 return ERR_IO_PENDING;
435 }
436
437 void FakeBlockingStreamSocket::SetNextReadShouldBlock() {
438 DCHECK(!should_block_read_);
439 should_block_read_ = true;
440 }
441
442 void FakeBlockingStreamSocket::UnblockRead() {
443 DCHECK(should_block_read_);
444 should_block_read_ = false;
420 445
421 // If the operation is still pending in the underlying transport, immediately 446 // If the operation is still pending in the underlying transport, immediately
422 // return - OnCompleted() will handle invoking the callback once the transport 447 // return - OnReadCompleted() will handle invoking the callback once the
423 // has completed. 448 // transport has completed.
424 if (!have_result_) 449 if (pending_read_result_ == ERR_IO_PENDING)
450 return;
451 int result = pending_read_result_;
452 pending_read_result_ = ERR_IO_PENDING;
453 base::ResetAndReturn(&pending_read_callback_).Run(result);
454 }
455
456 void FakeBlockingStreamSocket::WaitForRead() {
457 DCHECK(should_block_read_);
458 DCHECK(!read_loop_);
459
460 if (pending_read_result_ != ERR_IO_PENDING)
461 return;
462 read_loop_.reset(new base::RunLoop);
463 read_loop_->Run();
464 read_loop_.reset();
465 DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
466 }
467
468 void FakeBlockingStreamSocket::SetNextWriteShouldBlock() {
469 DCHECK(!should_block_write_);
470 should_block_write_ = true;
471 }
472
473 void FakeBlockingStreamSocket::UnblockWrite() {
474 DCHECK(should_block_write_);
475 should_block_write_ = false;
476
477 if (!pending_write_buf_)
Ryan Sleevi 2014/04/02 22:09:13 comment nit: Can you add a comment about what this
davidben 2014/04/03 19:38:36 Done.
425 return; 478 return;
426 479
427 have_result_ = false; 480 int rv = transport_->Write(pending_write_buf_, pending_write_len_,
428 481 pending_write_callback_);
429 base::ResetAndReturn(&user_callback_).Run(pending_result_); 482 pending_write_buf_ = NULL;
483 pending_write_len_ = -1;
484 if (rv == ERR_IO_PENDING) {
485 pending_write_callback_.Reset();
486 } else {
487 base::ResetAndReturn(&pending_write_callback_).Run(rv);
488 }
430 } 489 }
431 490
432 int FakeBlockingStreamSocket::BlockingState::RunWrappedFunction( 491 void FakeBlockingStreamSocket::WaitForWrite() {
433 IOBuffer* buf, 492 DCHECK(should_block_write_);
434 int len, 493 DCHECK(!write_loop_);
435 const CompletionCallback& callback) {
436 494
437 // The callback to be called by the underlying transport. Either forward 495 if (pending_write_buf_)
438 // directly to the user's callback if not set to block, or intercept it with 496 return;
439 // OnCompleted so that the user's callback is not invoked until Unblock() is 497 write_loop_.reset(new base::RunLoop);
440 // called. 498 write_loop_->Run();
441 CompletionCallback transport_callback = 499 write_loop_.reset();
442 !should_block_ ? callback : base::Bind(&BlockingState::OnCompleted, 500 DCHECK(pending_write_buf_);
443 base::Unretained(this));
444 int rv = wrapped_function_.Run(buf, len, transport_callback);
445 if (should_block_) {
446 user_callback_ = callback;
447 // May have completed synchronously.
448 have_result_ = (rv != ERR_IO_PENDING);
449 pending_result_ = rv;
450 return ERR_IO_PENDING;
451 }
452
453 return rv;
454 } 501 }
455 502
456 void FakeBlockingStreamSocket::BlockingState::OnCompleted(int result) { 503 void FakeBlockingStreamSocket::OnReadCompleted(int result) {
457 if (should_block_) { 504 if (should_block_read_) {
458 // Store the result so that the callback can be invoked once Unblock() is 505 // Store the result so that the callback can be invoked once Unblock() is
459 // called. 506 // called.
460 have_result_ = true; 507 pending_read_result_ = result;
461 pending_result_ = result; 508
509 // Stop the WaitForRead() call if any.
510 if (read_loop_)
511 read_loop_->Quit();
462 return; 512 return;
463 } 513 }
464 514
465 // Otherwise, the Unblock() function was called before the underlying 515 // Otherwise, the Unblock() function was called before the underlying
466 // transport completed, so run the user's callback immediately. 516 // transport completed, so run the user's callback immediately.
467 base::ResetAndReturn(&user_callback_).Run(result); 517 base::ResetAndReturn(&pending_read_callback_).Run(result);
468 } 518 }
469 519
470 // CompletionCallback that will delete the associated StreamSocket when 520 // CompletionCallback that will delete the associated StreamSocket when
471 // the callback is invoked. 521 // the callback is invoked.
472 class DeleteSocketCallback : public TestCompletionCallbackBase { 522 class DeleteSocketCallback : public TestCompletionCallbackBase {
473 public: 523 public:
474 explicit DeleteSocketCallback(StreamSocket* socket) 524 explicit DeleteSocketCallback(StreamSocket* socket)
475 : socket_(socket), 525 : socket_(socket),
476 callback_(base::Bind(&DeleteSocketCallback::OnComplete, 526 callback_(base::Bind(&DeleteSocketCallback::OnComplete,
477 base::Unretained(this))) {} 527 base::Unretained(this))) {}
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 rv = callback.WaitForResult(); 608 rv = callback.WaitForResult();
559 scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo(); 609 scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
560 sock->GetSSLCertRequestInfo(request_info.get()); 610 sock->GetSSLCertRequestInfo(request_info.get());
561 sock->Disconnect(); 611 sock->Disconnect();
562 EXPECT_FALSE(sock->IsConnected()); 612 EXPECT_FALSE(sock->IsConnected());
563 613
564 return request_info; 614 return request_info;
565 } 615 }
566 }; 616 };
567 617
618 class SSLClientSocketFalseStartTest : public SSLClientSocketTest {
619 protected:
620 void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options,
621 const SSLConfig& client_config,
622 bool expect_false_start) {
623 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
624 server_options,
625 base::FilePath());
626 ASSERT_TRUE(test_server.Start());
627
628 AddressList addr;
629 ASSERT_TRUE(test_server.GetAddressList(&addr));
630
631 TestCompletionCallback callback;
632 scoped_ptr<StreamSocket> real_transport(
633 new TCPClientSocket(addr, NULL, NetLog::Source()));
634 scoped_ptr<FakeBlockingStreamSocket> transport(
635 new FakeBlockingStreamSocket(real_transport.Pass()));
636 int rv = callback.GetResult(transport->Connect(callback.callback()));
637 EXPECT_EQ(OK, rv);
638
639 FakeBlockingStreamSocket* raw_transport = transport.get();
640 scoped_ptr<SSLClientSocket> sock(
641 CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
642 test_server.host_port_pair(),
643 client_config));
644
645 // Connect. Stop before the client processes the first server leg
646 // (ServerHello, etc.)
647 raw_transport->SetNextReadShouldBlock();
648 rv = sock->Connect(callback.callback());
649 EXPECT_EQ(ERR_IO_PENDING, rv);
650 raw_transport->WaitForRead();
651
652 // Release the ServerHello and wait for the client to write
653 // ClientKeyExchange, etc. (A proxy for waiting for the entirety of the
654 // server's leg to complete, since it may span multiple reads.)
655 EXPECT_FALSE(callback.have_result());
656 raw_transport->SetNextWriteShouldBlock();
657 raw_transport->UnblockRead();
658 raw_transport->WaitForWrite();
659
660 // And, finally, release that and block the next server leg
661 // (ChangeCipherSpec, Finished). Note: callback.have_result() may or may not
662 // be true at this point depending on whether the client's second leg ended
663 // up in a write buffer or if it
Ryan Sleevi 2014/04/02 22:09:13 Incomplete comment?
davidben 2014/04/03 19:38:36 Done. (For additional context: callback.have_resul
664 raw_transport->SetNextReadShouldBlock();
665 raw_transport->UnblockWrite();
666
667 if (expect_false_start) {
668 // Because of False Start, the handshake should complete.
Ryan Sleevi 2014/04/02 22:09:13 comment nit: Expand this comment // When False St
davidben 2014/04/03 19:38:36 Done.
669 rv = callback.GetResult(rv);
670 EXPECT_EQ(OK, rv);
671 EXPECT_TRUE(sock->IsConnected());
672
673 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
674 static const int kRequestTextSize =
675 static_cast<int>(arraysize(request_text) - 1);
676 scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize));
677 memcpy(request_buffer->data(), request_text, kRequestTextSize);
678
679 // Write the request.
680 rv = callback.GetResult(sock->Write(request_buffer.get(),
681 kRequestTextSize,
682 callback.callback()));
683 EXPECT_EQ(kRequestTextSize, rv);
684
685 // The read will hang.
Ryan Sleevi 2014/04/02 22:09:13 comment nit: Explain why the read will hang (eg: i
davidben 2014/04/03 19:38:36 Done.
686 scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
687 rv = sock->Read(buf.get(), 4096, callback.callback());
688
689 // After releasing reads, the connection proceeds.
690 raw_transport->UnblockRead();
691 rv = callback.GetResult(rv);
692 EXPECT_LT(0, rv);
693 } else {
694 // False Start is not enabled, so the handshake will not complete because
695 // the server second leg is blocked.
696 base::RunLoop().RunUntilIdle();
697 EXPECT_FALSE(callback.have_result());
698 }
699 }
700 };
701
568 //----------------------------------------------------------------------------- 702 //-----------------------------------------------------------------------------
569 703
570 // LogContainsSSLConnectEndEvent returns true if the given index in the given 704 // LogContainsSSLConnectEndEvent returns true if the given index in the given
571 // log is an SSL connect end event. The NSS sockets will cork in an attempt to 705 // log is an SSL connect end event. The NSS sockets will cork in an attempt to
572 // merge the first application data record with the Finished message when false 706 // merge the first application data record with the Finished message when false
573 // starting. However, in order to avoid the server timing out the handshake, 707 // starting. However, in order to avoid the server timing out the handshake,
574 // they'll give up waiting for application data and send the Finished after a 708 // they'll give up waiting for application data and send the Finished after a
575 // timeout. This means that an SSL connect end event may appear as a socket 709 // timeout. This means that an SSL connect end event may appear as a socket
576 // write. 710 // write.
577 static bool LogContainsSSLConnectEndEvent( 711 static bool LogContainsSSLConnectEndEvent(
(...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after
2120 EXPECT_TRUE(sock->IsConnected()); 2254 EXPECT_TRUE(sock->IsConnected());
2121 log.GetEntries(&entries); 2255 log.GetEntries(&entries);
2122 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 2256 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
2123 2257
2124 EXPECT_FALSE(sock->signed_cert_timestamps_received_); 2258 EXPECT_FALSE(sock->signed_cert_timestamps_received_);
2125 2259
2126 sock->Disconnect(); 2260 sock->Disconnect();
2127 EXPECT_FALSE(sock->IsConnected()); 2261 EXPECT_FALSE(sock->IsConnected());
2128 } 2262 }
2129 2263
2264 // This test is only enabled on NSS until False Start support is added for
2265 // OpenSSL. http://crbug.com/354132
2266 #if defined(USE_NSS)
2267 #define MAYBE_FalseStartEnabled FalseStartEnabled
2268 #else
2269 #define MAYBE_FalseStartEnabled DISABLED_FalseStartEnabled
2270 #endif // USE_NSS
2271 TEST_F(SSLClientSocketFalseStartTest, MAYBE_FalseStartEnabled) {
2272 // False Start requires NPN and a PFS cipher suite.
Ryan Sleevi 2014/04/02 22:09:13 comment nit: s/PFS/forward-secret/ (match your com
davidben 2014/04/03 19:38:36 Done.
2273 SpawnedTestServer::SSLOptions server_options;
2274 server_options.key_exchanges =
2275 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
2276 server_options.support_npn = true;
2277 SSLConfig client_config;
2278 client_config.next_protos.push_back("http/1.1");
2279 TestFalseStart(server_options, client_config, true);
2280 }
2281
2282 // Test that False Start is disabled without NPN.
2283 TEST_F(SSLClientSocketFalseStartTest, NoNPN) {
2284 SpawnedTestServer::SSLOptions server_options;
2285 server_options.key_exchanges =
2286 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
2287 SSLConfig client_config;
Ryan Sleevi 2014/04/02 22:09:13 client_config.next_protos.clear() , to ensure that
davidben 2014/04/03 19:38:36 Done.
2288 TestFalseStart(server_options, client_config, false);
2289 }
2290
2291 // Test that False Start is disabled without a forward-secret cipher.
2292 TEST_F(SSLClientSocketFalseStartTest, NoForwardSecrecy) {
2293 SpawnedTestServer::SSLOptions server_options;
2294 server_options.key_exchanges =
2295 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_RSA;
2296 server_options.support_npn = true;
2297 SSLConfig client_config;
2298 client_config.next_protos.push_back("http/1.1");
2299 TestFalseStart(server_options, client_config, false);
2300 }
2301
2130 } // namespace net 2302 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/test/spawned_test_server/base_test_server.h » ('j') | net/test/spawned_test_server/base_test_server.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698