ssl_client_socket_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// Use of this source code is governed by a BSD-style license that can be 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// found in the LICENSE file. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "net/socket/ssl_client_socket.h" 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "base/callback_helpers.h" 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "base/memory/ref_counted.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/base/address_list.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/base/io_buffer.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/base/net_errors.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/base/net_log.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/base/net_log_unittest.h" 142e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/base/test_completion_callback.h" 152e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/base/test_data_directory.h" 162e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/cert/mock_cert_verifier.h" 172e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/cert/test_root_certs.h" 18945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "net/dns/host_resolver.h" 19945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "net/http/transport_security_state.h" 20945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "net/socket/client_socket_factory.h" 212e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/socket/client_socket_handle.h" 222e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/socket/socket_test_util.h" 232e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/socket/tcp_client_socket.h" 242e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/ssl/ssl_cert_request_info.h" 25945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "net/ssl/ssl_config_service.h" 262e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org#include "net/test/cert_test_util.h" 27945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "net/test/spawned_test_server/spawned_test_server.h" 28945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "testing/gtest/include/gtest/gtest.h" 29945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#include "testing/platform_test.h" 30945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 31945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com//----------------------------------------------------------------------------- 32945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 33945a139553a9c9da03766213661d7f5fd6ed3042reed@android.comnamespace net { 34945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 35945a139553a9c9da03766213661d7f5fd6ed3042reed@android.comnamespace { 362e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 37945a139553a9c9da03766213661d7f5fd6ed3042reed@android.comconst SSLConfig kDefaultSSLConfig; 38945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 392e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// WrappedStreamSocket is a base class that wraps an existing StreamSocket, 402e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// forwarding the Socket and StreamSocket interfaces to the underlying 412e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// transport. 422e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// This is to provide a common base class for subclasses to override specific 432e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// StreamSocket methods for testing, while still communicating with a 'real' 442e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// StreamSocket. 452e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.orgclass WrappedStreamSocket : public StreamSocket { 462e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org public: 472e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org explicit WrappedStreamSocket(scoped_ptr<StreamSocket> transport) 482e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org : transport_(transport.Pass()) {} 492e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org virtual ~WrappedStreamSocket() {} 502e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 512e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // StreamSocket implementation: 522e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org virtual int Connect(const CompletionCallback& callback) OVERRIDE { 532e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org return transport_->Connect(callback); 542e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org } 552e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org virtual void Disconnect() OVERRIDE { transport_->Disconnect(); } 562e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org virtual bool IsConnected() const OVERRIDE { 57945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com return transport_->IsConnected(); 58945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com } 59945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com virtual bool IsConnectedAndIdle() const OVERRIDE { 60945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com return transport_->IsConnectedAndIdle(); 61945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com } 62945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE { 63945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com return transport_->GetPeerAddress(address); 64945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com } 65945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE { 66945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com return transport_->GetLocalAddress(address); 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const BoundNetLog& NetLog() const OVERRIDE { 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->NetLog(); 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void SetSubresourceSpeculation() OVERRIDE { 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport_->SetSubresourceSpeculation(); 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void SetOmniboxSpeculation() OVERRIDE { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport_->SetOmniboxSpeculation(); 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool WasEverUsed() const OVERRIDE { 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->WasEverUsed(); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool UsingTCPFastOpen() const OVERRIDE { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->UsingTCPFastOpen(); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool WasNpnNegotiated() const OVERRIDE { 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->WasNpnNegotiated(); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual NextProto GetNegotiatedProtocol() const OVERRIDE { 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->GetNegotiatedProtocol(); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->GetSSLInfo(ssl_info); 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Socket implementation: 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Read(IOBuffer* buf, 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE { 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->Read(buf, buf_len, callback); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Write(IOBuffer* buf, 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE { 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->Write(buf, buf_len, callback); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool SetReceiveBufferSize(int32 size) OVERRIDE { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->SetReceiveBufferSize(size); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool SetSendBufferSize(int32 size) OVERRIDE { 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->SetSendBufferSize(size); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com protected: 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport_; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// ReadBufferingStreamSocket is a wrapper for an existing StreamSocket that 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will ensure a certain amount of data is internally buffered before 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// satisfying a Read() request. It exists to mimic OS-level internal 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// buffering, but in a way to guarantee that X number of bytes will be 11915161620bee33efcb706685486c9ce0fb51a72bbreed@android.com// returned to callers of Read(), regardless of how quickly the OS receives 12015161620bee33efcb706685486c9ce0fb51a72bbreed@android.com// them from the TestServer. 12115161620bee33efcb706685486c9ce0fb51a72bbreed@android.comclass ReadBufferingStreamSocket : public WrappedStreamSocket { 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com explicit ReadBufferingStreamSocket(scoped_ptr<StreamSocket> transport); 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~ReadBufferingStreamSocket() {} 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Socket implementation: 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Read(IOBuffer* buf, 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Sets the internal buffer to |size|. This must not be greater than 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the largest value supplied to Read() - that is, it does not handle 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // having "leftovers" at the end of Read(). 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Each call to Read() will be prevented from completion until at least 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // |size| data has been read. 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Set to 0 to turn off buffering, causing Read() to transparently 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // read via the underlying transport. 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void SetBufferSize(int size); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private: 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum State { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com STATE_NONE, 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com STATE_READ, 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com STATE_READ_COMPLETE, 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 14615161620bee33efcb706685486c9ce0fb51a72bbreed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int DoLoop(int result); 14815161620bee33efcb706685486c9ce0fb51a72bbreed@android.com int DoRead(); 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int DoReadComplete(int result); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void OnReadCompleted(int result); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com State state_; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<GrowableIOBuffer> read_buffer_; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buffer_size_; 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> user_read_buf_; 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CompletionCallback user_read_callback_; 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comReadBufferingStreamSocket::ReadBufferingStreamSocket( 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport) 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : WrappedStreamSocket(transport.Pass()), 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_(new GrowableIOBuffer()), 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer_size_(0) {} 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid ReadBufferingStreamSocket::SetBufferSize(int size) { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DCHECK(!user_read_buf_.get()); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer_size_ = size; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->SetCapacity(size); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint ReadBufferingStreamSocket::Read(IOBuffer* buf, 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) { 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (buffer_size_ == 0) 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->Read(buf, buf_len, callback); 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (buf_len < buffer_size_) 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ERR_UNEXPECTED; 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state_ = STATE_READ; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com user_read_buf_ = buf; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int result = DoLoop(OK); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result == ERR_IO_PENDING) 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com user_read_callback_ = callback; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com user_read_buf_ = NULL; 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint ReadBufferingStreamSocket::DoLoop(int result) { 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = result; 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com State current_state = state_; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state_ = STATE_NONE; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (current_state) { 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case STATE_READ: 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = DoRead(); 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case STATE_READ_COMPLETE: 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = DoReadComplete(rv); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case STATE_NONE: 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTREACHED() << "Unexpected state: " << current_state; 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = ERR_UNEXPECTED; 207fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com break; 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (rv != ERR_IO_PENDING && state_ != STATE_NONE); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rv; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint ReadBufferingStreamSocket::DoRead() { 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state_ = STATE_READ_COMPLETE; 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport_->Read(read_buffer_.get(), 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->RemainingCapacity(), 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Bind(&ReadBufferingStreamSocket::OnReadCompleted, 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this))); 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rv; 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint ReadBufferingStreamSocket::DoReadComplete(int result) { 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state_ = STATE_NONE; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result <= 0) 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->set_offset(read_buffer_->offset() + result); 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (read_buffer_->RemainingCapacity() > 0) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state_ = STATE_READ; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return OK; 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(user_read_buf_->data(), 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->StartOfBuffer(), 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->capacity()); 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_buffer_->set_offset(0); 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return read_buffer_->capacity(); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid ReadBufferingStreamSocket::OnReadCompleted(int result) { 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = DoLoop(result); 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result == ERR_IO_PENDING) 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com user_read_buf_ = NULL; 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::ResetAndReturn(&user_read_callback_).Run(result); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Simulates synchronously receiving an error during Read() or Write() 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SynchronousErrorStreamSocket : public WrappedStreamSocket { 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com explicit SynchronousErrorStreamSocket(scoped_ptr<StreamSocket> transport); 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SynchronousErrorStreamSocket() {} 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Socket implementation: 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Read(IOBuffer* buf, 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Write(IOBuffer* buf, 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE; 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Sets the next Read() call and all future calls to return |error|. 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // If there is already a pending asynchronous read, the configured error 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // will not be returned until that asynchronous read has completed and Read() 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // is called again. 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void SetNextReadError(Error error) { 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DCHECK_GE(0, error); 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_read_error_ = true; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_read_error_ = error; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Sets the next Write() call and all future calls to return |error|. 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // If there is already a pending asynchronous write, the configured error 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // will not be returned until that asynchronous write has completed and 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Write() is called again. 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void SetNextWriteError(Error error) { 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DCHECK_GE(0, error); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_write_error_ = true; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_write_error_ = error; 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private: 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool have_read_error_; 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pending_read_error_; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool have_write_error_; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pending_write_error_; 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DISALLOW_COPY_AND_ASSIGN(SynchronousErrorStreamSocket); 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSynchronousErrorStreamSocket::SynchronousErrorStreamSocket( 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport) 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : WrappedStreamSocket(transport.Pass()), 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_read_error_(false), 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_read_error_(OK), 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_write_error_(false), 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_write_error_(OK) {} 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SynchronousErrorStreamSocket::Read(IOBuffer* buf, 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) { 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (have_read_error_) 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return pending_read_error_; 307fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com return transport_->Read(buf, buf_len, callback); 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SynchronousErrorStreamSocket::Write(IOBuffer* buf, 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) { 31377f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com if (have_write_error_) 31477f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com return pending_write_error_; 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return transport_->Write(buf, buf_len, callback); 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// FakeBlockingStreamSocket wraps an existing StreamSocket and simulates the 319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// underlying transport needing to complete things asynchronously in a 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// deterministic manner (e.g.: independent of the TestServer and the OS's 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// semantics). 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass FakeBlockingStreamSocket : public WrappedStreamSocket { 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com explicit FakeBlockingStreamSocket(scoped_ptr<StreamSocket> transport); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~FakeBlockingStreamSocket() {} 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 327fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // Socket implementation: 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Read(IOBuffer* buf, 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE { 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return read_state_.RunWrappedFunction(buf, buf_len, callback); 332fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual int Write(IOBuffer* buf, 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int buf_len, 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback) OVERRIDE { 336fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return write_state_.RunWrappedFunction(buf, buf_len, callback); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Causes the next call to Read() to return ERR_IO_PENDING, not completing 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (invoking the callback) until UnblockRead() has been called and the 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // underlying transport has completed. 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void SetNextReadShouldBlock() { read_state_.SetShouldBlock(); } 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void UnblockRead() { read_state_.Unblock(); } 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Causes the next call to Write() to return ERR_IO_PENDING, not completing 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (invoking the callback) until UnblockWrite() has been called and the 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // underlying transport has completed. 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void SetNextWriteShouldBlock() { write_state_.SetShouldBlock(); } 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void UnblockWrite() { write_state_.Unblock(); } 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private: 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Tracks the state for simulating a blocking Read/Write operation. 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com class BlockingState { 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Wrapper for the underlying Socket function to call (ie: Read/Write). 35677f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com typedef base::Callback<int(IOBuffer*, int, const CompletionCallback&)> 35777f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com WrappedSocketFunction; 35877f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 35977f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com explicit BlockingState(const WrappedSocketFunction& function); 36077f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com ~BlockingState() {} 36177f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 36277f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // Sets the next call to RunWrappedFunction() to block, returning 363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // ERR_IO_PENDING and not invoking the user callback until Unblock() is 36477f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // called. 36577f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com void SetShouldBlock(); 36677f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 367fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // Unblocks the currently blocked pending function, invoking the user 36877f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // callback if the results are immediately available. 36977f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // Note: It's not valid to call this unless SetShouldBlock() has been 37077f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // called beforehand. 37177f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com void Unblock(); 37277f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 37377f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // Performs the wrapped socket function on the underlying transport. If 37477f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // configured to block via SetShouldBlock(), then |user_callback| will not 37577f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // be invoked until Unblock() has been called. 37677f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com int RunWrappedFunction(IOBuffer* buf, 37777f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com int len, 37877f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com const CompletionCallback& user_callback); 37977f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 38077f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com private: 38177f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com // Handles completion from the underlying wrapped socket function. 38277f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com void OnCompleted(int result); 38377f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com 38477f0ef726f1f8b6769ed2509171afce8bac00b23reed@android.com WrappedSocketFunction wrapped_function_; 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool should_block_; 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool have_result_; 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pending_result_; 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CompletionCallback user_callback_; 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BlockingState read_state_; 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BlockingState write_state_; 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DISALLOW_COPY_AND_ASSIGN(FakeBlockingStreamSocket); 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3975383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comFakeBlockingStreamSocket::FakeBlockingStreamSocket( 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport) 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : WrappedStreamSocket(transport.Pass()), 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com read_state_(base::Bind(&Socket::Read, 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(transport_.get()))), 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com write_state_(base::Bind(&Socket::Write, 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(transport_.get()))) {} 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comFakeBlockingStreamSocket::BlockingState::BlockingState( 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const WrappedSocketFunction& function) 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : wrapped_function_(function), 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should_block_(false), 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_result_(false), 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_result_(OK) {} 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid FakeBlockingStreamSocket::BlockingState::SetShouldBlock() { 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DCHECK(!should_block_); 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should_block_ = true; 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid FakeBlockingStreamSocket::BlockingState::Unblock() { 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DCHECK(should_block_); 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should_block_ = false; 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // If the operation is still pending in the underlying transport, immediately 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return - OnCompleted() will handle invoking the callback once the transport 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // has completed. 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!have_result_) 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_result_ = false; 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4295383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com base::ResetAndReturn(&user_callback_).Run(pending_result_); 4305383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4325383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comint FakeBlockingStreamSocket::BlockingState::RunWrappedFunction( 4335383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com IOBuffer* buf, 4345383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com int len, 4355383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com const CompletionCallback& callback) { 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // The callback to be called by the underlying transport. Either forward 4385383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com // directly to the user's callback if not set to block, or intercept it with 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // OnCompleted so that the user's callback is not invoked until Unblock() is 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // called. 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CompletionCallback transport_callback = 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !should_block_ ? callback : base::Bind(&BlockingState::OnCompleted, 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this)); 4446fc321a18acc8c6437735007240eefe7054e83b0reed@google.com int rv = wrapped_function_.Run(buf, len, transport_callback); 4456fc321a18acc8c6437735007240eefe7054e83b0reed@google.com if (should_block_) { 4466fc321a18acc8c6437735007240eefe7054e83b0reed@google.com user_callback_ = callback; 4476fc321a18acc8c6437735007240eefe7054e83b0reed@google.com // May have completed synchronously. 4486fc321a18acc8c6437735007240eefe7054e83b0reed@google.com have_result_ = (rv != ERR_IO_PENDING); 4496fc321a18acc8c6437735007240eefe7054e83b0reed@google.com pending_result_ = rv; 4506fc321a18acc8c6437735007240eefe7054e83b0reed@google.com return ERR_IO_PENDING; 4516fc321a18acc8c6437735007240eefe7054e83b0reed@google.com } 4526fc321a18acc8c6437735007240eefe7054e83b0reed@google.com 4536fc321a18acc8c6437735007240eefe7054e83b0reed@google.com return rv; 4546fc321a18acc8c6437735007240eefe7054e83b0reed@google.com} 4556fc321a18acc8c6437735007240eefe7054e83b0reed@google.com 4566fc321a18acc8c6437735007240eefe7054e83b0reed@google.comvoid FakeBlockingStreamSocket::BlockingState::OnCompleted(int result) { 4576fc321a18acc8c6437735007240eefe7054e83b0reed@google.com if (should_block_) { 458945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Store the result so that the callback can be invoked once Unblock() is 459945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // called. 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com have_result_ = true; 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pending_result_ = result; 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Otherwise, the Unblock() function was called before the underlying 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transport completed, so run the user's callback immediately. 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::ResetAndReturn(&user_callback_).Run(result); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// CompletionCallback that will delete the associated StreamSocket when 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// the callback is invoked. 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass DeleteSocketCallback : public TestCompletionCallbackBase { 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com explicit DeleteSocketCallback(StreamSocket* socket) 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : socket_(socket), 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callback_(base::Bind(&DeleteSocketCallback::OnComplete, 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this))) {} 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~DeleteSocketCallback() {} 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CompletionCallback& callback() const { return callback_; } 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private: 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void OnComplete(int result) { 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (socket_) { 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete socket_; 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com socket_ = NULL; 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ADD_FAILURE() << "Deleting socket twice"; 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SetResult(result); 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com StreamSocket* socket_; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CompletionCallback callback_; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DISALLOW_COPY_AND_ASSIGN(DeleteSocketCallback); 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SSLClientSocketTest : public PlatformTest { 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public: 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLClientSocketTest() 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : socket_factory_(ClientSocketFactory::GetDefaultFactory()), 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cert_verifier_(new MockCertVerifier), 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport_security_state_(new TransportSecurityState) { 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cert_verifier_->set_default_result(OK); 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com context_.cert_verifier = cert_verifier_.get(); 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com context_.transport_security_state = transport_security_state_.get(); 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com protected: 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> CreateSSLClientSocket( 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport_socket, 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const HostPortPair& host_and_port, 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SSLConfig& ssl_config) { 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com connection->SetSocket(transport_socket.Pass()); 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return socket_factory_->CreateSSLClientSocket( 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com connection.Pass(), host_and_port, ssl_config, context_); 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ClientSocketFactory* socket_factory_; 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<MockCertVerifier> cert_verifier_; 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<TransportSecurityState> transport_security_state_; 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLClientSocketContext context_; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Verifies the correctness of GetSSLCertRequestInfo. 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com protected: 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Creates a test server with the given SSLOptions, connects to it and returns 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the SSLCertRequestInfo reported by the socket. 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<SSLCertRequestInfo> GetCertRequest( 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions ssl_options) { 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server( 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!test_server.Start()) 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!test_server.GetAddressList(&addr)) 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog log; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo(); 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->GetSSLCertRequestInfo(request_info.get()); 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->Disconnect(); 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return request_info; 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//----------------------------------------------------------------------------- 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// LogContainsSSLConnectEndEvent returns true if the given index in the given 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// log is an SSL connect end event. The NSS sockets will cork in an attempt to 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// merge the first application data record with the Finished message when false 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// starting. However, in order to avoid the server timing out the handshake, 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// they'll give up waiting for application data and send the Finished after a 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// timeout. This means that an SSL connect end event may appear as a socket 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// write. 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool LogContainsSSLConnectEndEvent( 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const CapturingNetLog::CapturedEntryList& log, 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int i) { 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return LogContainsEndEvent(log, i, NetLog::TYPE_SSL_CONNECT) || 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com LogContainsEvent( 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log, i, NetLog::TYPE_SOCKET_BYTES_SENT, NetLog::PHASE_NONE); 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} // namespace 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Connect) { 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 595a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 596fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com TestCompletionCallback callback; 597a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com CapturingNetLog log; 598a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com scoped_ptr<StreamSocket> transport( 599a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 600a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com int rv = transport->Connect(callback.callback()); 601a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com if (rv == ERR_IO_PENDING) 602a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com rv = callback.WaitForResult(); 603a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_EQ(OK, rv); 604a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 605a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 606a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 607a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 608a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_FALSE(sock->IsConnected()); 609a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 610a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com rv = sock->Connect(callback.callback()); 611a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 612a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com CapturingNetLog::CapturedEntryList entries; 613a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com log.GetEntries(&entries); 614a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 615a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com if (rv == ERR_IO_PENDING) 616a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com rv = callback.WaitForResult(); 617a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_EQ(OK, rv); 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->Disconnect(); 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, ConnectExpired) { 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions ssl_options( 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions::CERT_EXPIRED); 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server( 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cert_verifier_->set_default_result(ERR_CERT_DATE_INVALID); 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog log; 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 647a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 650a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_FALSE(sock->IsConnected()); 651a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 652a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com rv = sock->Connect(callback.callback()); 653a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com 654a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com CapturingNetLog::CapturedEntryList entries; 655a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com log.GetEntries(&entries); 656a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 657a964028843ec3f69b3b2e556426ff881d1fcb4b2reed@android.com if (rv == ERR_IO_PENDING) 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CERT_DATE_INVALID, rv); 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Rather than testing whether or not the underlying socket is connected, 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // test that the handshake has finished. This is because it may be 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // desirable to disconnect the socket before showing a user prompt, since 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the user may take indefinitely long to respond. 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, ConnectMismatched) { 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions ssl_options( 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME); 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server( 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cert_verifier_->set_default_result(ERR_CERT_COMMON_NAME_INVALID); 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog log; 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog::CapturedEntryList entries; 699bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com log.GetEntries(&entries); 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 701bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com if (rv == ERR_IO_PENDING) 702bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com rv = callback.WaitForResult(); 703fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, rv); 705bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Rather than testing whether or not the underlying socket is connected, 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // test that the handshake has finished. This is because it may be 708bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com // desirable to disconnect the socket before showing a user prompt, since 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the user may take indefinitely long to respond. 710bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com log.GetEntries(&entries); 711bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 712bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com} 713bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com 714bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com// Attempt to connect to a page which requests a client certificate. It should 715bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com// return an error code on connect. 716bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.comTEST_F(SSLClientSocketTest, ConnectClientAuthCertRequested) { 717bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com SpawnedTestServer::SSLOptions ssl_options; 718bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com ssl_options.request_client_certificate = true; 719fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SpawnedTestServer test_server( 720bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 721bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com ASSERT_TRUE(test_server.Start()); 722bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com 723bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com AddressList addr; 724bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 725bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com 726bb13586591bd412a0372aeb85d44159d2fa3f947reed@android.com TestCompletionCallback callback; 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog log; 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog::CapturedEntryList entries; 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Because we prematurely kill the handshake at CertificateRequest, 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the server may still send data (notably the ServerHelloDone) 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // after the error is returned. As a result, the SSL_CONNECT may not 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // be the last entry. See http://crbug.com/54445. We use 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // ExpectLogContainsSomewhere instead of 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // LogContainsSSLConnectEndEvent to avoid assuming, e.g., only one 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // extra read instead of two. This occurs before the handshake ends, 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // so the corking logic of LogContainsSSLConnectEndEvent isn't 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // necessary. 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO(davidben): When SSL_RestartHandshakeAfterCertReq in NSS is 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fixed and we can respond to the first CertificateRequest 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // without closing the socket, add a unit test for sending the 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // certificate. This test may still be useful as we'll want to close 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the socket on a timeout if the user takes a long time to pick a 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // cert. Related bug: https://bugzilla.mozilla.org/show_bug.cgi?id=542832 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ExpectLogContainsSomewhere( 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com entries, 0, NetLog::TYPE_SSL_CONNECT, NetLog::PHASE_END); 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Connect to a server requesting optional client authentication. Send it a 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// null certificate. It should allow the connection. 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// TODO(davidben): Also test providing an actual certificate. 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) { 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::SSLOptions ssl_options; 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_options.request_client_certificate = true; 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server( 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog log; 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, &log, NetLog::Source())); 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLConfig ssl_config = kDefaultSSLConfig; 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config.send_client_cert = true; 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config.client_cert = NULL; 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), ssl_config)); 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Our test server accepts certificate-less connections. 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO(davidben): Add a test which requires them and verify the error. 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CapturingNetLog::CapturedEntryList entries; 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com log.GetEntries(&entries); 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // We responded to the server's certificate request with a Certificate 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // message with no client certificate in it. ssl_info.client_cert_sent 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // should be false in this case. 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLInfo ssl_info; 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->GetSSLInfo(&ssl_info); 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(ssl_info.client_cert_sent); 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->Disconnect(); 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(sock->IsConnected()); 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// TODO(wtc): Add unit tests for IsConnectedAndIdle: 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// - Server closes an SSL connection (with a close_notify alert message). 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// - Server closes the underlying TCP connection directly. 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// - Server sends data unexpectedly. 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Read) { 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 838087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com ASSERT_TRUE(test_server.Start()); 839087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 840087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com AddressList addr; 841087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 842087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 843087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com TestCompletionCallback callback; 844087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com scoped_ptr<StreamSocket> transport( 845087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com new TCPClientSocket(addr, NULL, NetLog::Source())); 846087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com int rv = transport->Connect(callback.callback()); 847087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com if (rv == ERR_IO_PENDING) 848087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = callback.WaitForResult(); 849087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_EQ(OK, rv); 850087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 851087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 852087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 853087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 854087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = sock->Connect(callback.callback()); 855087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com if (rv == ERR_IO_PENDING) 856087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = callback.WaitForResult(); 857087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_EQ(OK, rv); 858087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_TRUE(sock->IsConnected()); 859087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 860087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 861087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com scoped_refptr<IOBuffer> request_buffer( 862087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com new IOBuffer(arraysize(request_text) - 1)); 863087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 864087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 865087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = sock->Write( 866087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com request_buffer.get(), arraysize(request_text) - 1, callback.callback()); 867087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 868087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 869087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com if (rv == ERR_IO_PENDING) 870087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = callback.WaitForResult(); 871087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 872087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 873087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 874087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com for (;;) { 875087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = sock->Read(buf.get(), 4096, callback.callback()); 876087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 877087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 878087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com if (rv == ERR_IO_PENDING) 879087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com rv = callback.WaitForResult(); 880087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 881087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com EXPECT_GE(rv, 0); 882087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com if (rv <= 0) 883087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com break; 884087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com } 885087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com} 886087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 887087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com// Tests that the SSLClientSocket properly handles when the underlying transport 888087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com// synchronously returns an error code - such as if an intermediary terminates 889087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com// the socket connection uncleanly. 890087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com// This is a regression test for http://crbug.com/238536 891087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.comTEST_F(SSLClientSocketTest, Read_WithSynchronousError) { 892087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 893087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com SpawnedTestServer::kLocalhost, 894087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com base::FilePath()); 895087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com ASSERT_TRUE(test_server.Start()); 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> real_transport( 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, NULL, NetLog::Source())); 903fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scoped_ptr<SynchronousErrorStreamSocket> transport( 904087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com new SynchronousErrorStreamSocket(real_transport.Pass())); 905087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com int rv = callback.GetResult(transport->Connect(callback.callback())); 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Disable TLS False Start to avoid handshake non-determinism. 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLConfig ssl_config; 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config.false_start_enabled = false; 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SynchronousErrorStreamSocket* raw_transport = transport.get(); 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock( 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CreateSSLClientSocket(transport.PassAs<StreamSocket>(), 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_server.host_port_pair(), 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config)); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult(sock->Connect(callback.callback())); 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const int kRequestTextSize = 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static_cast<int>(arraysize(request_text) - 1); 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize)); 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(request_buffer->data(), request_text, kRequestTextSize); 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult( 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->Write(request_buffer.get(), kRequestTextSize, callback.callback())); 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(kRequestTextSize, rv); 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Simulate an unclean/forcible shutdown. 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_transport->SetNextReadError(ERR_CONNECTION_RESET); 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Note: This test will hang if this bug has regressed. Simply checking that 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // rv != ERR_IO_PENDING is insufficient, as ERR_IO_PENDING is a legitimate 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // result when using a dedicated task runner for NSS. 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult(sock->Read(buf.get(), 4096, callback.callback())); 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if !defined(USE_OPENSSL) 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SSLClientSocketNSS records the error exactly 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CONNECTION_RESET, rv); 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SSLClientSocketOpenSSL treats any errors as a simple EOF. 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(0, rv); 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Tests that the SSLClientSocket properly handles when the underlying transport 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// asynchronously returns an error code while writing data - such as if an 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// intermediary terminates the socket connection uncleanly. 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// This is a regression test for http://crbug.com/249848 9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Write_WithSynchronousError) { 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 960087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 961087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com AddressList addr; 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 963087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com 964087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com TestCompletionCallback callback; 965087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com scoped_ptr<StreamSocket> real_transport( 966087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com new TCPClientSocket(addr, NULL, NetLog::Source())); 967087d5aafb18b88dfc6c6a5dbf59160c8be914e62reed@google.com // Note: |error_socket|'s ownership is handed to |transport|, but a pointer 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // is retained in order to configure additional errors. 9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SynchronousErrorStreamSocket> error_socket( 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new SynchronousErrorStreamSocket(real_transport.Pass())); 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SynchronousErrorStreamSocket* raw_error_socket = error_socket.get(); 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<FakeBlockingStreamSocket> transport( 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new FakeBlockingStreamSocket(error_socket.PassAs<StreamSocket>())); 9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FakeBlockingStreamSocket* raw_transport = transport.get(); 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = callback.GetResult(transport->Connect(callback.callback())); 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Disable TLS False Start to avoid handshake non-determinism. 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLConfig ssl_config; 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config.false_start_enabled = false; 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock( 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CreateSSLClientSocket(transport.PassAs<StreamSocket>(), 9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_server.host_port_pair(), 9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config)); 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult(sock->Connect(callback.callback())); 988fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com EXPECT_EQ(OK, rv); 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const int kRequestTextSize = 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static_cast<int>(arraysize(request_text) - 1); 9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize)); 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(request_buffer->data(), request_text, kRequestTextSize); 9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Simulate an unclean/forcible shutdown on the underlying socket. 9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // However, simulate this error asynchronously. 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_error_socket->SetNextWriteError(ERR_CONNECTION_RESET); 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_transport->SetNextWriteShouldBlock(); 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // This write should complete synchronously, because the TLS ciphertext 10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // can be created and placed into the outgoing buffers independent of the 10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // underlying transport. 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult( 10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sock->Write(request_buffer.get(), kRequestTextSize, callback.callback())); 10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(kRequestTextSize, rv); 10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Read(buf.get(), 4096, callback.callback()); 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_IO_PENDING, rv); 10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Now unblock the outgoing request, having it fail with the connection 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // being reset. 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_transport->UnblockWrite(); 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Note: This will cause an inifite loop if this bug has regressed. Simply 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // checking that rv != ERR_IO_PENDING is insufficient, as ERR_IO_PENDING 1020fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // is a legitimate result when using a dedicated task runner for NSS. 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult(rv); 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if !defined(USE_OPENSSL) 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SSLClientSocketNSS records the error exactly 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CONNECTION_RESET, rv); 10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SSLClientSocketOpenSSL treats any errors as a simple EOF. 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(0, rv); 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Test the full duplex mode, with Read and Write pending at the same time. 10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// This test also serves as a regression test for http://crbug.com/29815. 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Read_FullDuplex) { 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; // Used for everything except Write. 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, NULL, NetLog::Source())); 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Issue a "hanging" Read first. 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Read(buf.get(), 4096, callback.callback()); 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // We haven't written the request, so there should be no response yet. 10655383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com ASSERT_EQ(ERR_IO_PENDING, rv); 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Write the request. 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // The request is padded with a User-Agent header to a size that causes the 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around. 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // This tests the fix for http://crbug.com/29815. 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name "; 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 3770; ++i) 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com request_text.push_back('*'); 10742e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org request_text.append("\r\n\r\n"); 10752e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org scoped_refptr<IOBuffer> request_buffer(new StringIOBuffer(request_text)); 10762e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 10772e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org TestCompletionCallback callback2; // Used for Write only. 10782e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org rv = sock->Write( 1079945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com request_buffer.get(), request_text.size(), callback2.callback()); 1080945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 1081945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1082945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com if (rv == ERR_IO_PENDING) 1083945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com rv = callback2.WaitForResult(); 1084945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com EXPECT_EQ(static_cast<int>(request_text.size()), rv); 1085945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1086945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Now get the Read result. 1087945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com rv = callback.WaitForResult(); 10882e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org EXPECT_GT(rv, 0); 10892e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org} 10902e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 1091945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com// Attempts to Read() and Write() from an SSLClientSocketNSS in full duplex 1092945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com// mode when the underlying transport is blocked on sending data. When the 1093945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com// underlying transport completes due to an error, it should invoke both the 10942e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// Read() and Write() callbacks. If the socket is deleted by the Read() 10952e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org// callback, the Write() callback should not be invoked. 1096945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com// Regression test for http://crbug.com/232633 1097945a139553a9c9da03766213661d7f5fd6ed3042reed@android.comTEST_F(SSLClientSocketTest, Read_DeleteWhilePendingFullDuplex) { 1098945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 1099945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com SpawnedTestServer::kLocalhost, 1100945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com base::FilePath()); 1101945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com ASSERT_TRUE(test_server.Start()); 1102945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1103945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com AddressList addr; 11042e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org ASSERT_TRUE(test_server.GetAddressList(&addr)); 11052e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 11062e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org TestCompletionCallback callback; 1107945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_ptr<StreamSocket> real_transport( 1108945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com new TCPClientSocket(addr, NULL, NetLog::Source())); 1109945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Note: |error_socket|'s ownership is handed to |transport|, but a pointer 1110945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // is retained in order to configure additional errors. 1111945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_ptr<SynchronousErrorStreamSocket> error_socket( 1112945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com new SynchronousErrorStreamSocket(real_transport.Pass())); 1113945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com SynchronousErrorStreamSocket* raw_error_socket = error_socket.get(); 1114945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_ptr<FakeBlockingStreamSocket> transport( 1115945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com new FakeBlockingStreamSocket(error_socket.PassAs<StreamSocket>())); 1116945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com FakeBlockingStreamSocket* raw_transport = transport.get(); 1117945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1118945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com int rv = callback.GetResult(transport->Connect(callback.callback())); 1119945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com EXPECT_EQ(OK, rv); 1120945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1121945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Disable TLS False Start to avoid handshake non-determinism. 1122945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com SSLConfig ssl_config; 1123945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com ssl_config.false_start_enabled = false; 1124945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1125945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_ptr<SSLClientSocket> sock = 1126945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com CreateSSLClientSocket(transport.PassAs<StreamSocket>(), 1127945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com test_server.host_port_pair(), 1128945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com ssl_config); 1129945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1130945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com rv = callback.GetResult(sock->Connect(callback.callback())); 1131945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com EXPECT_EQ(OK, rv); 1132945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com EXPECT_TRUE(sock->IsConnected()); 1133945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1134945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name "; 1135945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com request_text.append(20 * 1024, '*'); 1136945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com request_text.append("\r\n\r\n"); 1137945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_refptr<DrainableIOBuffer> request_buffer(new DrainableIOBuffer( 1138945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com new StringIOBuffer(request_text), request_text.size())); 1139945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1140945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Simulate errors being returned from the underlying Read() and Write() ... 1141945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com raw_error_socket->SetNextReadError(ERR_CONNECTION_RESET); 1142945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com raw_error_socket->SetNextWriteError(ERR_CONNECTION_RESET); 1143945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // ... but have those errors returned asynchronously. Because the Write() will 1144945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // return first, this will trigger the error. 1145945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com raw_transport->SetNextReadShouldBlock(); 1146945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com raw_transport->SetNextWriteShouldBlock(); 1147945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1148945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Enqueue a Read() before calling Write(), which should "hang" due to 1149945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // the ERR_IO_PENDING caused by SetReadShouldBlock() and thus return. 1150945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com SSLClientSocket* raw_sock = sock.get(); 1151945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com DeleteSocketCallback read_callback(sock.release()); 1152945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com scoped_refptr<IOBuffer> read_buf(new IOBuffer(4096)); 11532e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org rv = raw_sock->Read(read_buf.get(), 4096, read_callback.callback()); 11542e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 11552e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // Ensure things didn't complete synchronously, otherwise |sock| is invalid. 1156945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com ASSERT_EQ(ERR_IO_PENDING, rv); 1157945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com ASSERT_FALSE(read_callback.have_result()); 1158945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 1159945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#if !defined(USE_OPENSSL) 1160945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // NSS follows a pattern where a call to PR_Write will only consume as 11612e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // much data as it can encode into application data records before the 1162945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // internal memio buffer is full, which should only fill if writing a large 1163945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // amount of data and the underlying transport is blocked. Once this happens, 1164945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // NSS will return (total size of all application data records it wrote) - 1, 11652e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // with the caller expected to resume with the remaining unsent data. 11662e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // 11672e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // This causes SSLClientSocketNSS::Write to return that it wrote some data 11682e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // before it will return ERR_IO_PENDING, so make an extra call to Write() to 11692e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // get the socket in the state needed for the test below. 1170945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // 11712e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // This is not needed for OpenSSL, because for OpenSSL, 11722e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // SSL_MODE_ENABLE_PARTIAL_WRITE is not specified - thus 11732e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // SSLClientSocketOpenSSL::Write() will not return until all of 1174945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // |request_buffer| has been written to the underlying BIO (although not 11752e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // necessarily the underlying transport). 1176945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com rv = callback.GetResult(raw_sock->Write(request_buffer.get(), 11772e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org request_buffer->BytesRemaining(), 11782e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org callback.callback())); 11792e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org ASSERT_LT(0, rv); 1180945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com request_buffer->DidConsume(rv); 11812e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org 1182945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com // Guard to ensure that |request_buffer| was larger than all of the internal 11832e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // buffers (transport, memio, NSS) along the way - otherwise the next call 11842e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org // to Write() will crash with an invalid buffer. 11852e086190e55a01dc2f7b74df6f2828e8cac2b9abkbr@chromium.org ASSERT_LT(0, request_buffer->BytesRemaining()); 1186945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com#endif 1187945a139553a9c9da03766213661d7f5fd6ed3042reed@android.com 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Attempt to write the remaining data. NSS will not be able to consume the 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // application data because the internal buffers are full, while OpenSSL will 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return that its blocked because the underlying transport is blocked. 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = raw_sock->Write(request_buffer.get(), 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com request_buffer->BytesRemaining(), 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callback.callback()); 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_EQ(ERR_IO_PENDING, rv); 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_FALSE(callback.have_result()); 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Now unblock Write(), which will invoke OnSendComplete and (eventually) 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call the Read() callback, deleting the socket and thus aborting calling 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the Write() callback. 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_transport->UnblockWrite(); 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = read_callback.WaitForResult(); 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if !defined(USE_OPENSSL) 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // NSS records the error exactly. 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CONNECTION_RESET, rv); 1207e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com#else 1208b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // OpenSSL treats any errors as a simple EOF. 12099e1ec1a52985cce9db3a0d0e8d448b82a32e70cbskia.committer@gmail.com EXPECT_EQ(0, rv); 1210e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com#endif 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1212e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com // The Write callback should not have been called. 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(callback.have_result()); 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Tests that the SSLClientSocket does not crash if data is received on the 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// transport socket after a failing write. This can occur if we have a Write 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// error in a SPDY socket. 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Regression test for http://crbug.com/335557 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Read_WithWriteError) { 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> real_transport( 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, NULL, NetLog::Source())); 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Note: |error_socket|'s ownership is handed to |transport|, but a pointer 1233e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com // is retained in order to configure additional errors. 1234b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com scoped_ptr<SynchronousErrorStreamSocket> error_socket( 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new SynchronousErrorStreamSocket(real_transport.Pass())); 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SynchronousErrorStreamSocket* raw_error_socket = error_socket.get(); 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<FakeBlockingStreamSocket> transport( 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new FakeBlockingStreamSocket(error_socket.PassAs<StreamSocket>())); 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FakeBlockingStreamSocket* raw_transport = transport.get(); 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = callback.GetResult(transport->Connect(callback.callback())); 1242fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com EXPECT_EQ(OK, rv); 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Disable TLS False Start to avoid handshake non-determinism. 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SSLConfig ssl_config; 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ssl_config.false_start_enabled = false; 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock( 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CreateSSLClientSocket(transport.PassAs<StreamSocket>(), 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_server.host_port_pair(), 1251e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com ssl_config)); 1252e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.GetResult(sock->Connect(callback.callback())); 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(sock->IsConnected()); 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Send a request so there is something to read from the socket. 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 1259b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com static const int kRequestTextSize = 1260dff53c26e7ef80da4767433ecfe17741a059e247reed@google.com static_cast<int>(arraysize(request_text) - 1); 1261b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize)); 1262b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com memcpy(request_buffer->data(), request_text, kRequestTextSize); 1263b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com 1264b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com rv = callback.GetResult( 1265b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com sock->Write(request_buffer.get(), kRequestTextSize, callback.callback())); 1266b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com EXPECT_EQ(kRequestTextSize, rv); 1267b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com 1268b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // Start a hanging read. 1269c7a37c7bb2279d8c15d6fcbaf38f59dbd727eb6crobertphillips@google.com TestCompletionCallback read_callback; 1270b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com raw_transport->SetNextReadShouldBlock(); 1271b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 1272b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com rv = sock->Read(buf.get(), 4096, read_callback.callback()); 1273b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com EXPECT_EQ(ERR_IO_PENDING, rv); 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1275b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com // Perform another write, but have it fail. Write a request larger than the 1276b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // internal socket buffers so that the request hits the underlying transport 1277b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // socket and detects the error. 1278b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com std::string long_request_text = 1279b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com "GET / HTTP/1.1\r\nUser-Agent: long browser name "; 1280b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com long_request_text.append(20 * 1024, '*'); 1281b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com long_request_text.append("\r\n\r\n"); 1282b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com scoped_refptr<DrainableIOBuffer> long_request_buffer(new DrainableIOBuffer( 1283b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com new StringIOBuffer(long_request_text), long_request_text.size())); 1284b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com 1285b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com raw_error_socket->SetNextWriteError(ERR_CONNECTION_RESET); 1286b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com 1287b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // Write as much data as possible until hitting an error. This is necessary 1288b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // for NSS. PR_Write will only consume as much data as it can encode into 1289b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com // application data records before the internal memio buffer is full, which 1290b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com // should only fill if writing a large amount of data and the underlying 1291b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // transport is blocked. Once this happens, NSS will return (total size of all 1292b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // application data records it wrote) - 1, with the caller expected to resume 1293b0889a5aa610552bf306edc8d9a35d2d601acdb9robertphillips@google.com // with the remaining unsent data. 1294b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com do { 1295b95eaa8d0842a8bba97f0bc7e19cfd9172d09722robertphillips@google.com rv = callback.GetResult(sock->Write(long_request_buffer.get(), 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com long_request_buffer->BytesRemaining(), 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callback.callback())); 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv > 0) { 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com long_request_buffer->DidConsume(rv); 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Abort if the entire buffer is ever consumed. 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_LT(0, long_request_buffer->BytesRemaining()); 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (rv > 0); 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if !defined(USE_OPENSSL) 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // NSS records the error exactly. 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CONNECTION_RESET, rv); 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // OpenSSL treats the reset as a generic protocol error. 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Release the read. Some bytes should go through. 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com raw_transport->UnblockRead(); 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = read_callback.WaitForResult(); 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1317fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // Per the fix for http://crbug.com/249848, write failures currently break 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reads. Change this assertion if they're changed to not collide. 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(ERR_CONNECTION_RESET, rv); 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Read_SmallChunks) { 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.Start()); 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddressList addr; 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestCompletionCallback callback; 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<StreamSocket> transport( 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new TCPClientSocket(addr, NULL, NetLog::Source())); 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rv = transport->Connect(callback.callback()); 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Connect(callback.callback()); 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(OK, rv); 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> request_buffer( 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new IOBuffer(arraysize(request_text) - 1)); 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Write( 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com request_buffer.get(), arraysize(request_text) - 1, callback.callback()); 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 1359e1b75b4096c8ba9a569ae33d580806edd3c4a97arobertphillips@google.com 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_refptr<IOBuffer> buf(new IOBuffer(1)); 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = sock->Read(buf.get(), 1, callback.callback()); 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv == ERR_IO_PENDING) 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rv = callback.WaitForResult(); 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_GE(rv, 0); 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rv <= 0) 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTEST_F(SSLClientSocketTest, Read_ManySmallRecords) { 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SpawnedTestServer::kLocalhost, 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::FilePath()); 1378c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com ASSERT_TRUE(test_server.Start()); 1379c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com 1380c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com AddressList addr; 138117a2c919d095797c364d407a5dbdb4d60533b953reed@google.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 138217a2c919d095797c364d407a5dbdb4d60533b953reed@google.com 138317a2c919d095797c364d407a5dbdb4d60533b953reed@google.com TestCompletionCallback callback; 138417a2c919d095797c364d407a5dbdb4d60533b953reed@google.com 138517a2c919d095797c364d407a5dbdb4d60533b953reed@google.com scoped_ptr<StreamSocket> real_transport( 138617a2c919d095797c364d407a5dbdb4d60533b953reed@google.com new TCPClientSocket(addr, NULL, NetLog::Source())); 138717a2c919d095797c364d407a5dbdb4d60533b953reed@google.com scoped_ptr<ReadBufferingStreamSocket> transport( 138817a2c919d095797c364d407a5dbdb4d60533b953reed@google.com new ReadBufferingStreamSocket(real_transport.Pass())); 138917a2c919d095797c364d407a5dbdb4d60533b953reed@google.com ReadBufferingStreamSocket* raw_transport = transport.get(); 139017a2c919d095797c364d407a5dbdb4d60533b953reed@google.com int rv = callback.GetResult(transport->Connect(callback.callback())); 139117a2c919d095797c364d407a5dbdb4d60533b953reed@google.com ASSERT_EQ(OK, rv); 139217a2c919d095797c364d407a5dbdb4d60533b953reed@google.com 139317a2c919d095797c364d407a5dbdb4d60533b953reed@google.com scoped_ptr<SSLClientSocket> sock( 139417a2c919d095797c364d407a5dbdb4d60533b953reed@google.com CreateSSLClientSocket(transport.PassAs<StreamSocket>(), 139517a2c919d095797c364d407a5dbdb4d60533b953reed@google.com test_server.host_port_pair(), 13966862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org kDefaultSSLConfig)); 13970c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 13980c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = callback.GetResult(sock->Connect(callback.callback())); 139945fb8b60137c65106b7903285672d0f8a8041f97skia.committer@gmail.com ASSERT_EQ(OK, rv); 14000c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org ASSERT_TRUE(sock->IsConnected()); 14010c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 14020c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org const char request_text[] = "GET /ssl-many-small-records HTTP/1.0\r\n\r\n"; 14030c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org scoped_refptr<IOBuffer> request_buffer( 14040c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org new IOBuffer(arraysize(request_text) - 1)); 140545fb8b60137c65106b7903285672d0f8a8041f97skia.committer@gmail.com memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 14060c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 14070c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = callback.GetResult(sock->Write( 14080c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org request_buffer.get(), arraysize(request_text) - 1, callback.callback())); 14090c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org ASSERT_GT(rv, 0); 141045fb8b60137c65106b7903285672d0f8a8041f97skia.committer@gmail.com ASSERT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 14110c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 14120c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // Note: This relies on SSLClientSocketNSS attempting to read up to 17K of 141317a2c919d095797c364d407a5dbdb4d60533b953reed@google.com // data (the max SSL record size) at a time. Ensure that at least 15K worth 14140c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // of SSL data is buffered first. The 15K of buffered data is made up of 14150c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // many smaller SSL records (the TestServer writes along 1350 byte 14166862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org // plaintext boundaries), although there may also be a few records that are 14176862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org // smaller or larger, due to timing and SSL False Start. 14186862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org // 15K was chosen because 15K is smaller than the 17K (max) read issued by 14196862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org // the SSLClientSocket implementation, and larger than the minimum amount 14206862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org // of ciphertext necessary to contain the 8K of plaintext requested below. 14216862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org raw_transport->SetBufferSize(15000); 14220c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 142317a2c919d095797c364d407a5dbdb4d60533b953reed@google.com scoped_refptr<IOBuffer> buffer(new IOBuffer(8192)); 14246862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org rv = callback.GetResult(sock->Read(buffer.get(), 8192, callback.callback())); 14256862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org ASSERT_EQ(rv, 8192); 142617a2c919d095797c364d407a5dbdb4d60533b953reed@google.com} 14276862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org 14286862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.orgTEST_F(SSLClientSocketTest, Read_Interrupted) { 14296862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 14306862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org SpawnedTestServer::kLocalhost, 14316862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org base::FilePath()); 14326862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org ASSERT_TRUE(test_server.Start()); 14336862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org 14346862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org AddressList addr; 14356862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org ASSERT_TRUE(test_server.GetAddressList(&addr)); 14366862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org 14376862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org TestCompletionCallback callback; 14386862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org scoped_ptr<StreamSocket> transport( 14396862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org new TCPClientSocket(addr, NULL, NetLog::Source())); 14400c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org int rv = transport->Connect(callback.callback()); 14410c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org if (rv == ERR_IO_PENDING) 14426862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org rv = callback.WaitForResult(); 14430c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_EQ(OK, rv); 14446862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org 14450c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 14460c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 14470c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 14480c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = sock->Connect(callback.callback()); 144945fb8b60137c65106b7903285672d0f8a8041f97skia.committer@gmail.com if (rv == ERR_IO_PENDING) 14500c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = callback.WaitForResult(); 14510c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_EQ(OK, rv); 14520c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 14530c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 14540c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org scoped_refptr<IOBuffer> request_buffer( 145517a2c919d095797c364d407a5dbdb4d60533b953reed@google.com new IOBuffer(arraysize(request_text) - 1)); 145617a2c919d095797c364d407a5dbdb4d60533b953reed@google.com memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 14570d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14580d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = sock->Write( 14594bb50b22fce5c4031549976cf7b04d63cc22e624skia.committer@gmail.com request_buffer.get(), arraysize(request_text) - 1, callback.callback()); 14600d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 14610d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14620d099557feb99707c8f601746f46f5a295eb33b7reed@google.com if (rv == ERR_IO_PENDING) 14634bb50b22fce5c4031549976cf7b04d63cc22e624skia.committer@gmail.com rv = callback.WaitForResult(); 14640d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 14650d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14660d099557feb99707c8f601746f46f5a295eb33b7reed@google.com // Do a partial read and then exit. This test should not crash! 14670d099557feb99707c8f601746f46f5a295eb33b7reed@google.com scoped_refptr<IOBuffer> buf(new IOBuffer(512)); 14680d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = sock->Read(buf.get(), 512, callback.callback()); 14690d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_TRUE(rv > 0 || rv == ERR_IO_PENDING); 14700d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14710d099557feb99707c8f601746f46f5a295eb33b7reed@google.com if (rv == ERR_IO_PENDING) 14720d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = callback.WaitForResult(); 14730d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14740d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_GT(rv, 0); 14750d099557feb99707c8f601746f46f5a295eb33b7reed@google.com} 14760d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14770d099557feb99707c8f601746f46f5a295eb33b7reed@google.comTEST_F(SSLClientSocketTest, Read_FullLogging) { 14780d099557feb99707c8f601746f46f5a295eb33b7reed@google.com SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 14790d099557feb99707c8f601746f46f5a295eb33b7reed@google.com SpawnedTestServer::kLocalhost, 14800d099557feb99707c8f601746f46f5a295eb33b7reed@google.com base::FilePath()); 14810d099557feb99707c8f601746f46f5a295eb33b7reed@google.com ASSERT_TRUE(test_server.Start()); 14820d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 14830d099557feb99707c8f601746f46f5a295eb33b7reed@google.com AddressList addr; 14840d099557feb99707c8f601746f46f5a295eb33b7reed@google.com ASSERT_TRUE(test_server.GetAddressList(&addr)); 148524bd210f2e2cf66f356b4e98f7801631089b8aa3reed@google.com 1486c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com TestCompletionCallback callback; 14874bb50b22fce5c4031549976cf7b04d63cc22e624skia.committer@gmail.com CapturingNetLog log; 1488c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com log.SetLogLevel(NetLog::LOG_ALL); 14896862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org scoped_ptr<StreamSocket> transport( 14906862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org new TCPClientSocket(addr, &log, NetLog::Source())); 1491c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com int rv = transport->Connect(callback.callback()); 149224bd210f2e2cf66f356b4e98f7801631089b8aa3reed@google.com if (rv == ERR_IO_PENDING) 149324bd210f2e2cf66f356b4e98f7801631089b8aa3reed@google.com rv = callback.WaitForResult(); 149424bd210f2e2cf66f356b4e98f7801631089b8aa3reed@google.com EXPECT_EQ(OK, rv); 149524bd210f2e2cf66f356b4e98f7801631089b8aa3reed@google.com 1496c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 1497c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 149828552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org 14990d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = sock->Connect(callback.callback()); 15000d099557feb99707c8f601746f46f5a295eb33b7reed@google.com if (rv == ERR_IO_PENDING) 15010d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = callback.WaitForResult(); 15024bb50b22fce5c4031549976cf7b04d63cc22e624skia.committer@gmail.com EXPECT_EQ(OK, rv); 15030d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_TRUE(sock->IsConnected()); 15040d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 15050d099557feb99707c8f601746f46f5a295eb33b7reed@google.com const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 15064bb50b22fce5c4031549976cf7b04d63cc22e624skia.committer@gmail.com scoped_refptr<IOBuffer> request_buffer( 15070d099557feb99707c8f601746f46f5a295eb33b7reed@google.com new IOBuffer(arraysize(request_text) - 1)); 15080d099557feb99707c8f601746f46f5a295eb33b7reed@google.com memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 15090d099557feb99707c8f601746f46f5a295eb33b7reed@google.com 15100d099557feb99707c8f601746f46f5a295eb33b7reed@google.com rv = sock->Write( 15110d099557feb99707c8f601746f46f5a295eb33b7reed@google.com request_buffer.get(), arraysize(request_text) - 1, callback.callback()); 15120d099557feb99707c8f601746f46f5a295eb33b7reed@google.com EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 15134af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org 15144af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org if (rv == ERR_IO_PENDING) 15154af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org rv = callback.WaitForResult(); 15164af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 15174af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org 15184af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org CapturingNetLog::CapturedEntryList entries; 15194af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org log.GetEntries(&entries); 15204af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org size_t last_index = ExpectLogContainsSomewhereAfter( 15214af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org entries, 5, NetLog::TYPE_SSL_SOCKET_BYTES_SENT, NetLog::PHASE_NONE); 15224af6280aa366a02540f34c48f89ea73ce3d27974mike@reedtribe.org 1523c518710d9a99c4d0adf759a102f4a1cb582f5939reed@google.com scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); 15248d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org for (;;) { 15253df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org rv = sock->Read(buf.get(), 4096, callback.callback()); 15266862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); 15273df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org 15283df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org if (rv == ERR_IO_PENDING) 152928552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org rv = callback.WaitForResult(); 15308d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org 15318d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org EXPECT_GE(rv, 0); 15328d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org if (rv <= 0) 15338d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org break; 15348d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org 15358d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org log.GetEntries(&entries); 15368d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org last_index = 15378d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org ExpectLogContainsSomewhereAfter(entries, 15388d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org last_index + 1, 15398d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, 15408d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org NetLog::PHASE_NONE); 15418d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org } 15428d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org} 15438d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org 15448d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org// Regression test for http://crbug.com/42538 15458d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.orgTEST_F(SSLClientSocketTest, PrematureApplicationData) { 15463df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 15473df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org SpawnedTestServer::kLocalhost, 15483df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org base::FilePath()); 154997514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org ASSERT_TRUE(test_server.Start()); 155097514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org 155197514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org AddressList addr; 155297514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org TestCompletionCallback callback; 1553af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 1554af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org static const unsigned char application_data[] = { 1555af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x17, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x01, 0x4b, 1556af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0xc2, 0xf8, 0xb2, 0xc1, 0x56, 0x42, 0xb9, 0x57, 0x7f, 0xde, 0x87, 0x46, 1557af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0xf7, 0xa3, 0x52, 0x42, 0x21, 0xf0, 0x13, 0x1c, 0x9c, 0x83, 0x88, 0xd6, 1558af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x93, 0x0c, 0xf6, 0x36, 0x30, 0x05, 0x7e, 0x20, 0xb5, 0xb5, 0x73, 0x36, 1559af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x53, 0x83, 0x0a, 0xfc, 0x17, 0x63, 0xbf, 0xa0, 0xe4, 0x42, 0x90, 0x0d, 1560af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x2f, 0x18, 0x6d, 0x20, 0xd8, 0x36, 0x3f, 0xfc, 0xe6, 0x01, 0xfa, 0x0f, 1561af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0xa5, 0x75, 0x7f, 0x09, 0x00, 0x04, 0x00, 0x16, 0x03, 0x01, 0x11, 0x57, 1562af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x0b, 0x00, 0x11, 0x53, 0x00, 0x11, 0x50, 0x00, 0x06, 0x22, 0x30, 0x82, 1563af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x06, 0x1e, 0x30, 0x82, 0x05, 0x06, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 1564af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 0x0a}; 1565af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 1566af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org // All reads and writes complete synchronously (async=false). 156797514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org MockRead data_reads[] = { 15687841c63136e8aa2d3aadbeab8432405abcd73c32skia.committer@gmail.com MockRead(SYNCHRONOUS, 156997514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org reinterpret_cast<const char*>(application_data), 1570af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org arraysize(application_data)), 1571af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org MockRead(SYNCHRONOUS, OK), }; 1572af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org 1573af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 157497514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org 15753df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org scoped_ptr<StreamSocket> transport( 157697514f22e4cb85a0d79b089a1eecd54d4a952291mike@reedtribe.org new MockTCPClientSocket(addr, NULL, &data)); 1577af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org int rv = transport->Connect(callback.callback()); 15783df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org if (rv == ERR_IO_PENDING) 15793df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org rv = callback.WaitForResult(); 158028552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org EXPECT_EQ(OK, rv); 15813df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org 1582af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 15833df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 15843df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org 15853df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org rv = sock->Connect(callback.callback()); 15863df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org if (rv == ERR_IO_PENDING) 158728552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org rv = callback.WaitForResult(); 15883df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); 15893df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org} 15903df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org 15913df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.orgTEST_F(SSLClientSocketTest, CipherSuiteDisables) { 15923df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org // Rather than exhaustively disabling every RC4 ciphersuite defined at 15938d551011966a1bc14a654dbde704f343c0e222b6mike@reedtribe.org // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml, 15943df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org // only disabling those cipher suites that the test server actually 159528552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org // implements. 1596af5c506cd6b63f43a0ebee2fb171ea55ba98e09fmike@reedtribe.org const uint16 kCiphersToDisable[] = {0x0005, // TLS_RSA_WITH_RC4_128_SHA 15973df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org }; 1598aebfa7e1b1e94f693f3e7beb6ad43cfcb0f69e98reed@google.com 15993df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org SpawnedTestServer::SSLOptions ssl_options; 16003df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org // Enable only RC4 on the test server. 16013df87cb36e9f9d2e04d2f81ac64cf3d778c33847mike@reedtribe.org ssl_options.bulk_ciphers = SpawnedTestServer::SSLOptions::BULK_CIPHER_RC4; 16020c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org SpawnedTestServer test_server( 160328552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 16046862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org ASSERT_TRUE(test_server.Start()); 16050c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 16060c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org AddressList addr; 160728552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org ASSERT_TRUE(test_server.GetAddressList(&addr)); 16086862cbad085729acb77825392c8c2a4f888a99cfmike@reedtribe.org 16090c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org TestCompletionCallback callback; 16100c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org CapturingNetLog log; 161128552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org scoped_ptr<StreamSocket> transport( 16120c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org new TCPClientSocket(addr, &log, NetLog::Source())); 16130c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org int rv = transport->Connect(callback.callback()); 16140c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org if (rv == ERR_IO_PENDING) 16150c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = callback.WaitForResult(); 16160c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_EQ(OK, rv); 16170c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 16180c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org SSLConfig ssl_config; 16190c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org for (size_t i = 0; i < arraysize(kCiphersToDisable); ++i) 16200c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]); 16210c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 16220c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 16230c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org transport.Pass(), test_server.host_port_pair(), ssl_config)); 16240c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 16250c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_FALSE(sock->IsConnected()); 162628552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org 16270c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = sock->Connect(callback.callback()); 16280c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org CapturingNetLog::CapturedEntryList entries; 16290c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org log.GetEntries(&entries); 16300c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 16310c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org 16320c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // NSS has special handling that maps a handshake_failure alert received 16330c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // immediately after a client_hello to be a mismatched cipher suite error, 16340c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // leading to ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When using OpenSSL or 16350c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // Secure Transport (OS X), the handshake_failure is bubbled up without any 16360c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // interpretation, leading to ERR_SSL_PROTOCOL_ERROR. Either way, a failure 16370c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org // indicates that no cipher suite was negotiated with the test server. 16380c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org if (rv == ERR_IO_PENDING) 16390c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org rv = callback.WaitForResult(); 16400c5c3867bdbde1005a7bbb9de9df93cc10e27782mike@reedtribe.org EXPECT_TRUE(rv == ERR_SSL_VERSION_OR_CIPHER_MISMATCH || 164128552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org rv == ERR_SSL_PROTOCOL_ERROR); 16425c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // The exact ordering differs between SSLClientSocketNSS (which issues an 16435c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // extra read) and SSLClientSocketMac (which does not). Just make sure the 16445c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // error appears somewhere in the log. 16455c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org log.GetEntries(&entries); 16465c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org ExpectLogContainsSomewhere( 16475c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org entries, 0, NetLog::TYPE_SSL_HANDSHAKE_ERROR, NetLog::PHASE_NONE); 16485c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org 16495c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // We cannot test sock->IsConnected(), as the NSS implementation disconnects 16505c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // the socket when it encounters an error, whereas other implementations 16515c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // leave it connected. 16525c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // Because this an error that the test server is mutually aware of, as opposed 16535c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // to being an error such as a certificate name mismatch, which is 16545c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // client-only, the exact index of the SSL connect end depends on how 16555c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // quickly the test server closes the underlying socket. If the test server 16565c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // closes before the IO message loop pumps messages, there may be a 0-byte 165728552e12a019bf5ae55c9e8602bbe216562d7a3emike@reedtribe.org // Read event in the NetLog due to TCPClientSocket picking up the EOF. As a 16585c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // result, the SSL connect end event will be the second-to-last entry, 16595c082a14acbb70eec2fd6dc5a4c134799f3d8535mike@reedtribe.org // rather than the last entry. 1660 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1) || 1661 LogContainsSSLConnectEndEvent(entries, -2)); 1662} 1663 1664// When creating an SSLClientSocket, it is allowed to pass in a 1665// ClientSocketHandle that is not obtained from a client socket pool. 1666// Here we verify that such a simple ClientSocketHandle, not associated with any 1667// client socket pool, can be destroyed safely. 1668TEST_F(SSLClientSocketTest, ClientSocketHandleNotFromPool) { 1669 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 1670 SpawnedTestServer::kLocalhost, 1671 base::FilePath()); 1672 ASSERT_TRUE(test_server.Start()); 1673 1674 AddressList addr; 1675 ASSERT_TRUE(test_server.GetAddressList(&addr)); 1676 1677 TestCompletionCallback callback; 1678 scoped_ptr<StreamSocket> transport( 1679 new TCPClientSocket(addr, NULL, NetLog::Source())); 1680 int rv = transport->Connect(callback.callback()); 1681 if (rv == ERR_IO_PENDING) 1682 rv = callback.WaitForResult(); 1683 EXPECT_EQ(OK, rv); 1684 1685 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle()); 1686 socket_handle->SetSocket(transport.Pass()); 1687 1688 scoped_ptr<SSLClientSocket> sock( 1689 socket_factory_->CreateSSLClientSocket(socket_handle.Pass(), 1690 test_server.host_port_pair(), 1691 kDefaultSSLConfig, 1692 context_)); 1693 1694 EXPECT_FALSE(sock->IsConnected()); 1695 rv = sock->Connect(callback.callback()); 1696 if (rv == ERR_IO_PENDING) 1697 rv = callback.WaitForResult(); 1698 EXPECT_EQ(OK, rv); 1699} 1700 1701// Verifies that SSLClientSocket::ExportKeyingMaterial return a success 1702// code and different keying label results in different keying material. 1703TEST_F(SSLClientSocketTest, ExportKeyingMaterial) { 1704 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 1705 SpawnedTestServer::kLocalhost, 1706 base::FilePath()); 1707 ASSERT_TRUE(test_server.Start()); 1708 1709 AddressList addr; 1710 ASSERT_TRUE(test_server.GetAddressList(&addr)); 1711 1712 TestCompletionCallback callback; 1713 1714 scoped_ptr<StreamSocket> transport( 1715 new TCPClientSocket(addr, NULL, NetLog::Source())); 1716 int rv = transport->Connect(callback.callback()); 1717 if (rv == ERR_IO_PENDING) 1718 rv = callback.WaitForResult(); 1719 EXPECT_EQ(OK, rv); 1720 1721 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 1722 transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 1723 1724 rv = sock->Connect(callback.callback()); 1725 if (rv == ERR_IO_PENDING) 1726 rv = callback.WaitForResult(); 1727 EXPECT_EQ(OK, rv); 1728 EXPECT_TRUE(sock->IsConnected()); 1729 1730 const int kKeyingMaterialSize = 32; 1731 const char* kKeyingLabel1 = "client-socket-test-1"; 1732 const char* kKeyingContext = ""; 1733 unsigned char client_out1[kKeyingMaterialSize]; 1734 memset(client_out1, 0, sizeof(client_out1)); 1735 rv = sock->ExportKeyingMaterial( 1736 kKeyingLabel1, false, kKeyingContext, client_out1, sizeof(client_out1)); 1737 EXPECT_EQ(rv, OK); 1738 1739 const char* kKeyingLabel2 = "client-socket-test-2"; 1740 unsigned char client_out2[kKeyingMaterialSize]; 1741 memset(client_out2, 0, sizeof(client_out2)); 1742 rv = sock->ExportKeyingMaterial( 1743 kKeyingLabel2, false, kKeyingContext, client_out2, sizeof(client_out2)); 1744 EXPECT_EQ(rv, OK); 1745 EXPECT_NE(memcmp(client_out1, client_out2, kKeyingMaterialSize), 0); 1746} 1747 1748// Verifies that SSLClientSocket::ClearSessionCache can be called without 1749// explicit NSS initialization. 1750TEST(SSLClientSocket, ClearSessionCache) { 1751 SSLClientSocket::ClearSessionCache(); 1752} 1753 1754// Test that the server certificates are properly retrieved from the underlying 1755// SSL stack. 1756TEST_F(SSLClientSocketTest, VerifyServerChainProperlyOrdered) { 1757 // The connection does not have to be successful. 1758 cert_verifier_->set_default_result(ERR_CERT_INVALID); 1759 1760 // Set up a test server with CERT_CHAIN_WRONG_ROOT. 1761 // This makes the server present redundant-server-chain.pem, which contains 1762 // intermediate certificates. 1763 SpawnedTestServer::SSLOptions ssl_options( 1764 SpawnedTestServer::SSLOptions::CERT_CHAIN_WRONG_ROOT); 1765 SpawnedTestServer test_server( 1766 SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()); 1767 ASSERT_TRUE(test_server.Start()); 1768 1769 AddressList addr; 1770 ASSERT_TRUE(test_server.GetAddressList(&addr)); 1771 1772 TestCompletionCallback callback; 1773 scoped_ptr<StreamSocket> transport( 1774 new TCPClientSocket(addr, NULL, NetLog::Source())); 1775 int rv = transport->Connect(callback.callback()); 1776 rv = callback.GetResult(rv); 1777 EXPECT_EQ(OK, rv); 1778 1779 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 1780 transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 1781 EXPECT_FALSE(sock->IsConnected()); 1782 rv = sock->Connect(callback.callback()); 1783 rv = callback.GetResult(rv); 1784 1785 EXPECT_EQ(ERR_CERT_INVALID, rv); 1786 EXPECT_TRUE(sock->IsConnected()); 1787 1788 // When given option CERT_CHAIN_WRONG_ROOT, SpawnedTestServer will present 1789 // certs from redundant-server-chain.pem. 1790 CertificateList server_certs = 1791 CreateCertificateListFromFile(GetTestCertsDirectory(), 1792 "redundant-server-chain.pem", 1793 X509Certificate::FORMAT_AUTO); 1794 1795 // Get the server certificate as received client side. 1796 scoped_refptr<X509Certificate> server_certificate = 1797 sock->GetUnverifiedServerCertificateChain(); 1798 1799 // Get the intermediates as received client side. 1800 const X509Certificate::OSCertHandles& server_intermediates = 1801 server_certificate->GetIntermediateCertificates(); 1802 1803 // Check that the unverified server certificate chain is properly retrieved 1804 // from the underlying ssl stack. 1805 ASSERT_EQ(4U, server_certs.size()); 1806 1807 EXPECT_TRUE(X509Certificate::IsSameOSCert( 1808 server_certificate->os_cert_handle(), server_certs[0]->os_cert_handle())); 1809 1810 ASSERT_EQ(3U, server_intermediates.size()); 1811 1812 EXPECT_TRUE(X509Certificate::IsSameOSCert(server_intermediates[0], 1813 server_certs[1]->os_cert_handle())); 1814 EXPECT_TRUE(X509Certificate::IsSameOSCert(server_intermediates[1], 1815 server_certs[2]->os_cert_handle())); 1816 EXPECT_TRUE(X509Certificate::IsSameOSCert(server_intermediates[2], 1817 server_certs[3]->os_cert_handle())); 1818 1819 sock->Disconnect(); 1820 EXPECT_FALSE(sock->IsConnected()); 1821} 1822 1823// This tests that SSLInfo contains a properly re-constructed certificate 1824// chain. That, in turn, verifies that GetSSLInfo is giving us the chain as 1825// verified, not the chain as served by the server. (They may be different.) 1826// 1827// CERT_CHAIN_WRONG_ROOT is redundant-server-chain.pem. It contains A 1828// (end-entity) -> B -> C, and C is signed by D. redundant-validated-chain.pem 1829// contains a chain of A -> B -> C2, where C2 is the same public key as C, but 1830// a self-signed root. Such a situation can occur when a new root (C2) is 1831// cross-certified by an old root (D) and has two different versions of its 1832// floating around. Servers may supply C2 as an intermediate, but the 1833// SSLClientSocket should return the chain that was verified, from 1834// verify_result, instead. 1835TEST_F(SSLClientSocketTest, VerifyReturnChainProperlyOrdered) { 1836 // By default, cause the CertVerifier to treat all certificates as 1837 // expired. 1838 cert_verifier_->set_default_result(ERR_CERT_DATE_INVALID); 1839 1840 // We will expect SSLInfo to ultimately contain this chain. 1841 CertificateList certs = 1842 CreateCertificateListFromFile(GetTestCertsDirectory(), 1843 "redundant-validated-chain.pem", 1844 X509Certificate::FORMAT_AUTO); 1845 ASSERT_EQ(3U, certs.size()); 1846 1847 X509Certificate::OSCertHandles temp_intermediates; 1848 temp_intermediates.push_back(certs[1]->os_cert_handle()); 1849 temp_intermediates.push_back(certs[2]->os_cert_handle()); 1850 1851 CertVerifyResult verify_result; 1852 verify_result.verified_cert = X509Certificate::CreateFromHandle( 1853 certs[0]->os_cert_handle(), temp_intermediates); 1854 1855 // Add a rule that maps the server cert (A) to the chain of A->B->C2 1856 // rather than A->B->C. 1857 cert_verifier_->AddResultForCert(certs[0].get(), verify_result, OK); 1858 1859 // Load and install the root for the validated chain. 1860 scoped_refptr<X509Certificate> root_cert = ImportCertFromFile( 1861 GetTestCertsDirectory(), "redundant-validated-chain-root.pem"); 1862 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert); 1863 ScopedTestRoot scoped_root(root_cert.get()); 1864 1865 // Set up a test server with CERT_CHAIN_WRONG_ROOT. 1866 SpawnedTestServer::SSLOptions ssl_options( 1867 SpawnedTestServer::SSLOptions::CERT_CHAIN_WRONG_ROOT); 1868 SpawnedTestServer test_server( 1869 SpawnedTestServer::TYPE_HTTPS, 1870 ssl_options, 1871 base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); 1872 ASSERT_TRUE(test_server.Start()); 1873 1874 AddressList addr; 1875 ASSERT_TRUE(test_server.GetAddressList(&addr)); 1876 1877 TestCompletionCallback callback; 1878 CapturingNetLog log; 1879 scoped_ptr<StreamSocket> transport( 1880 new TCPClientSocket(addr, &log, NetLog::Source())); 1881 int rv = transport->Connect(callback.callback()); 1882 if (rv == ERR_IO_PENDING) 1883 rv = callback.WaitForResult(); 1884 EXPECT_EQ(OK, rv); 1885 1886 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 1887 transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig)); 1888 EXPECT_FALSE(sock->IsConnected()); 1889 rv = sock->Connect(callback.callback()); 1890 1891 CapturingNetLog::CapturedEntryList entries; 1892 log.GetEntries(&entries); 1893 EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 1894 if (rv == ERR_IO_PENDING) 1895 rv = callback.WaitForResult(); 1896 1897 EXPECT_EQ(OK, rv); 1898 EXPECT_TRUE(sock->IsConnected()); 1899 log.GetEntries(&entries); 1900 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 1901 1902 SSLInfo ssl_info; 1903 sock->GetSSLInfo(&ssl_info); 1904 1905 // Verify that SSLInfo contains the corrected re-constructed chain A -> B 1906 // -> C2. 1907 const X509Certificate::OSCertHandles& intermediates = 1908 ssl_info.cert->GetIntermediateCertificates(); 1909 ASSERT_EQ(2U, intermediates.size()); 1910 EXPECT_TRUE(X509Certificate::IsSameOSCert(ssl_info.cert->os_cert_handle(), 1911 certs[0]->os_cert_handle())); 1912 EXPECT_TRUE(X509Certificate::IsSameOSCert(intermediates[0], 1913 certs[1]->os_cert_handle())); 1914 EXPECT_TRUE(X509Certificate::IsSameOSCert(intermediates[1], 1915 certs[2]->os_cert_handle())); 1916 1917 sock->Disconnect(); 1918 EXPECT_FALSE(sock->IsConnected()); 1919} 1920 1921TEST_F(SSLClientSocketCertRequestInfoTest, NoAuthorities) { 1922 SpawnedTestServer::SSLOptions ssl_options; 1923 ssl_options.request_client_certificate = true; 1924 scoped_refptr<SSLCertRequestInfo> request_info = GetCertRequest(ssl_options); 1925 ASSERT_TRUE(request_info.get()); 1926 EXPECT_EQ(0u, request_info->cert_authorities.size()); 1927} 1928 1929TEST_F(SSLClientSocketCertRequestInfoTest, TwoAuthorities) { 1930 const base::FilePath::CharType kThawteFile[] = 1931 FILE_PATH_LITERAL("thawte.single.pem"); 1932 const unsigned char kThawteDN[] = { 1933 0x30, 0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 1934 0x02, 0x5a, 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 1935 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 1936 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 1937 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 1938 0x55, 0x04, 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 1939 0x53, 0x47, 0x43, 0x20, 0x43, 0x41}; 1940 const size_t kThawteLen = sizeof(kThawteDN); 1941 1942 const base::FilePath::CharType kDiginotarFile[] = 1943 FILE_PATH_LITERAL("diginotar_root_ca.pem"); 1944 const unsigned char kDiginotarDN[] = { 1945 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 1946 0x02, 0x4e, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 1947 0x13, 0x09, 0x44, 0x69, 0x67, 0x69, 0x4e, 0x6f, 0x74, 0x61, 0x72, 0x31, 1948 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x44, 0x69, 1949 0x67, 0x69, 0x4e, 0x6f, 0x74, 0x61, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 1950 0x20, 0x43, 0x41, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 1951 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11, 0x69, 0x6e, 0x66, 0x6f, 1952 0x40, 0x64, 0x69, 0x67, 0x69, 0x6e, 0x6f, 0x74, 0x61, 0x72, 0x2e, 0x6e, 1953 0x6c}; 1954 const size_t kDiginotarLen = sizeof(kDiginotarDN); 1955 1956 SpawnedTestServer::SSLOptions ssl_options; 1957 ssl_options.request_client_certificate = true; 1958 ssl_options.client_authorities.push_back( 1959 GetTestClientCertsDirectory().Append(kThawteFile)); 1960 ssl_options.client_authorities.push_back( 1961 GetTestClientCertsDirectory().Append(kDiginotarFile)); 1962 scoped_refptr<SSLCertRequestInfo> request_info = GetCertRequest(ssl_options); 1963 ASSERT_TRUE(request_info.get()); 1964 ASSERT_EQ(2u, request_info->cert_authorities.size()); 1965 EXPECT_EQ(std::string(reinterpret_cast<const char*>(kThawteDN), kThawteLen), 1966 request_info->cert_authorities[0]); 1967 EXPECT_EQ( 1968 std::string(reinterpret_cast<const char*>(kDiginotarDN), kDiginotarLen), 1969 request_info->cert_authorities[1]); 1970} 1971 1972TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) { 1973 SpawnedTestServer::SSLOptions ssl_options; 1974 ssl_options.signed_cert_timestamps_tls_ext = "test"; 1975 1976 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 1977 ssl_options, 1978 base::FilePath()); 1979 ASSERT_TRUE(test_server.Start()); 1980 1981 AddressList addr; 1982 ASSERT_TRUE(test_server.GetAddressList(&addr)); 1983 1984 TestCompletionCallback callback; 1985 CapturingNetLog log; 1986 scoped_ptr<StreamSocket> transport( 1987 new TCPClientSocket(addr, &log, NetLog::Source())); 1988 int rv = transport->Connect(callback.callback()); 1989 if (rv == ERR_IO_PENDING) 1990 rv = callback.WaitForResult(); 1991 EXPECT_EQ(OK, rv); 1992 1993 SSLConfig ssl_config; 1994 ssl_config.signed_cert_timestamps_enabled = true; 1995 1996 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 1997 transport.Pass(), test_server.host_port_pair(), ssl_config)); 1998 1999 EXPECT_FALSE(sock->IsConnected()); 2000 2001 rv = sock->Connect(callback.callback()); 2002 2003 CapturingNetLog::CapturedEntryList entries; 2004 log.GetEntries(&entries); 2005 EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 2006 if (rv == ERR_IO_PENDING) 2007 rv = callback.WaitForResult(); 2008 EXPECT_EQ(OK, rv); 2009 EXPECT_TRUE(sock->IsConnected()); 2010 log.GetEntries(&entries); 2011 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 2012 2013#if !defined(USE_OPENSSL) 2014 EXPECT_TRUE(sock->signed_cert_timestamps_received_); 2015#else 2016 // Enabling CT for OpenSSL is currently a noop. 2017 EXPECT_FALSE(sock->signed_cert_timestamps_received_); 2018#endif 2019 2020 sock->Disconnect(); 2021 EXPECT_FALSE(sock->IsConnected()); 2022} 2023 2024// Test that enabling Signed Certificate Timestamps enables OCSP stapling. 2025TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledOCSP) { 2026 SpawnedTestServer::SSLOptions ssl_options; 2027 ssl_options.staple_ocsp_response = true; 2028 // The test server currently only knows how to generate OCSP responses 2029 // for a freshly minted certificate. 2030 ssl_options.server_certificate = SpawnedTestServer::SSLOptions::CERT_AUTO; 2031 2032 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 2033 ssl_options, 2034 base::FilePath()); 2035 ASSERT_TRUE(test_server.Start()); 2036 2037 AddressList addr; 2038 ASSERT_TRUE(test_server.GetAddressList(&addr)); 2039 2040 TestCompletionCallback callback; 2041 CapturingNetLog log; 2042 scoped_ptr<StreamSocket> transport( 2043 new TCPClientSocket(addr, &log, NetLog::Source())); 2044 int rv = transport->Connect(callback.callback()); 2045 if (rv == ERR_IO_PENDING) 2046 rv = callback.WaitForResult(); 2047 EXPECT_EQ(OK, rv); 2048 2049 SSLConfig ssl_config; 2050 // Enabling Signed Cert Timestamps ensures we request OCSP stapling for 2051 // Certificate Transparency verification regardless of whether the platform 2052 // is able to process the OCSP status itself. 2053 ssl_config.signed_cert_timestamps_enabled = true; 2054 2055 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 2056 transport.Pass(), test_server.host_port_pair(), ssl_config)); 2057 2058 EXPECT_FALSE(sock->IsConnected()); 2059 2060 rv = sock->Connect(callback.callback()); 2061 2062 CapturingNetLog::CapturedEntryList entries; 2063 log.GetEntries(&entries); 2064 EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 2065 if (rv == ERR_IO_PENDING) 2066 rv = callback.WaitForResult(); 2067 EXPECT_EQ(OK, rv); 2068 EXPECT_TRUE(sock->IsConnected()); 2069 log.GetEntries(&entries); 2070 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 2071 2072#if !defined(USE_OPENSSL) 2073 EXPECT_TRUE(sock->stapled_ocsp_response_received_); 2074#else 2075 // OCSP stapling isn't currently supported in the OpenSSL socket. 2076 EXPECT_FALSE(sock->stapled_ocsp_response_received_); 2077#endif 2078 2079 sock->Disconnect(); 2080 EXPECT_FALSE(sock->IsConnected()); 2081} 2082 2083TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsDisabled) { 2084 SpawnedTestServer::SSLOptions ssl_options; 2085 ssl_options.signed_cert_timestamps_tls_ext = "test"; 2086 2087 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, 2088 ssl_options, 2089 base::FilePath()); 2090 ASSERT_TRUE(test_server.Start()); 2091 2092 AddressList addr; 2093 ASSERT_TRUE(test_server.GetAddressList(&addr)); 2094 2095 TestCompletionCallback callback; 2096 CapturingNetLog log; 2097 scoped_ptr<StreamSocket> transport( 2098 new TCPClientSocket(addr, &log, NetLog::Source())); 2099 int rv = transport->Connect(callback.callback()); 2100 if (rv == ERR_IO_PENDING) 2101 rv = callback.WaitForResult(); 2102 EXPECT_EQ(OK, rv); 2103 2104 SSLConfig ssl_config; 2105 ssl_config.signed_cert_timestamps_enabled = false; 2106 2107 scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( 2108 transport.Pass(), test_server.host_port_pair(), ssl_config)); 2109 2110 EXPECT_FALSE(sock->IsConnected()); 2111 2112 rv = sock->Connect(callback.callback()); 2113 2114 CapturingNetLog::CapturedEntryList entries; 2115 log.GetEntries(&entries); 2116 EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); 2117 if (rv == ERR_IO_PENDING) 2118 rv = callback.WaitForResult(); 2119 EXPECT_EQ(OK, rv); 2120 EXPECT_TRUE(sock->IsConnected()); 2121 log.GetEntries(&entries); 2122 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 2123 2124 EXPECT_FALSE(sock->signed_cert_timestamps_received_); 2125 2126 sock->Disconnect(); 2127 EXPECT_FALSE(sock->IsConnected()); 2128} 2129 2130} // namespace net 2131