diff options
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/client_socket.h | 5 | ||||
-rw-r--r-- | net/base/client_socket_pool_unittest.cc | 3 | ||||
-rw-r--r-- | net/base/ssl_client_socket.h | 3 | ||||
-rw-r--r-- | net/base/ssl_client_socket_mac.cc | 14 | ||||
-rw-r--r-- | net/base/ssl_client_socket_mac.h | 1 | ||||
-rw-r--r-- | net/base/ssl_client_socket_nss.cc | 129 | ||||
-rw-r--r-- | net/base/ssl_client_socket_nss.h | 15 | ||||
-rw-r--r-- | net/base/ssl_client_socket_unittest.cc | 62 | ||||
-rw-r--r-- | net/base/ssl_client_socket_win.cc | 14 | ||||
-rw-r--r-- | net/base/ssl_client_socket_win.h | 1 | ||||
-rw-r--r-- | net/base/ssl_config_service.h | 9 | ||||
-rw-r--r-- | net/base/tcp_client_socket.h | 1 | ||||
-rw-r--r-- | net/base/tcp_client_socket_libevent.cc | 5 | ||||
-rw-r--r-- | net/base/tcp_client_socket_win.cc | 5 |
14 files changed, 193 insertions, 74 deletions
diff --git a/net/base/client_socket.h b/net/base/client_socket.h index 4d25b38..3553d52 100644 --- a/net/base/client_socket.h +++ b/net/base/client_socket.h @@ -33,11 +33,6 @@ class ClientSocket : public Socket { // virtual int Connect(CompletionCallback* callback) = 0; - // If a non-fatal error occurs during Connect, the consumer can call this - // method to re-Connect ignoring the error that occured. This call is only - // valid for certain errors. - virtual int ReconnectIgnoringLastError(CompletionCallback* callback) = 0; - // Called to disconnect a connected socket. Does nothing if the socket is // already disconnected. After calling Disconnect it is possible to call // Connect again to establish a new connection. diff --git a/net/base/client_socket_pool_unittest.cc b/net/base/client_socket_pool_unittest.cc index 8849781..dd51819 100644 --- a/net/base/client_socket_pool_unittest.cc +++ b/net/base/client_socket_pool_unittest.cc @@ -32,9 +32,6 @@ class MockClientSocket : public net::ClientSocket { connected_ = true; return net::OK; } - virtual int ReconnectIgnoringLastError(net::CompletionCallback* callback) { - return net::ERR_FAILED; - } virtual void Disconnect() { connected_ = false; } diff --git a/net/base/ssl_client_socket.h b/net/base/ssl_client_socket.h index 21b120b..8c9f05b 100644 --- a/net/base/ssl_client_socket.h +++ b/net/base/ssl_client_socket.h @@ -15,8 +15,7 @@ class SSLInfo; // // NOTE: The SSL handshake occurs within the Connect method after a TCP // connection is established. If a SSL error occurs during the handshake, -// Connect will fail. The consumer may choose to ignore certain SSL errors, -// such as a name mismatch, by calling ReconnectIgnoringLastError. +// Connect will fail. // class SSLClientSocket : public ClientSocket { public: diff --git a/net/base/ssl_client_socket_mac.cc b/net/base/ssl_client_socket_mac.cc index 5ed6c67..c43a4d1 100644 --- a/net/base/ssl_client_socket_mac.cc +++ b/net/base/ssl_client_socket_mac.cc @@ -279,12 +279,6 @@ int SSLClientSocketMac::Connect(CompletionCallback* callback) { return rv; } -int SSLClientSocketMac::ReconnectIgnoringLastError( - CompletionCallback* callback) { - // TODO(darin): implement me! - return ERR_FAILED; -} - void SSLClientSocketMac::Disconnect() { completed_handshake_ = false; @@ -451,7 +445,13 @@ int SSLClientSocketMac::DoLoop(int last_io_result) { int SSLClientSocketMac::DoConnect() { next_state_ = STATE_CONNECT_COMPLETE; - return transport_->Connect(&io_callback_); + + // The caller has to make sure that the transport socket is connected. If + // it isn't, we will eventually fail when trying to negotiate an SSL session. + // But we cannot call transport_->Connect(), as we do not know if there is + // any proxy negotiation that needs to be performed prior to establishing + // the SSL session. + return OK; } int SSLClientSocketMac::DoConnectComplete(int result) { diff --git a/net/base/ssl_client_socket_mac.h b/net/base/ssl_client_socket_mac.h index f195940..2efa031c 100644 --- a/net/base/ssl_client_socket_mac.h +++ b/net/base/ssl_client_socket_mac.h @@ -34,7 +34,6 @@ class SSLClientSocketMac : public SSLClientSocket { // ClientSocket methods: virtual int Connect(CompletionCallback* callback); - virtual int ReconnectIgnoringLastError(CompletionCallback* callback); virtual void Disconnect(); virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; diff --git a/net/base/ssl_client_socket_nss.cc b/net/base/ssl_client_socket_nss.cc index 4777ddc..aeccee3 100644 --- a/net/base/ssl_client_socket_nss.cc +++ b/net/base/ssl_client_socket_nss.cc @@ -15,6 +15,7 @@ #include <pk11pub.h> #undef Lock +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/nss_init.h" #include "base/string_util.h" @@ -129,6 +130,34 @@ int SSLClientSocketNSS::Init() { return OK; } +// As part of Connect(), the SSLClientSocketNSS object performs an SSL +// handshake. This requires network IO, which in turn calls +// BufferRecvComplete() with a non-zero byte count. This byte count eventually +// winds its way through the state machine and ends up being passed to the +// callback. For Read() and Write(), that's what we want. But for Connect(), +// the caller expects OK (i.e. 0) for success. +// +// The ConnectCallbackWrapper object changes the argument that gets passed +// to the callback function. Any positive value gets turned into OK. +class ConnectCallbackWrapper : + public CompletionCallbackImpl<ConnectCallbackWrapper> { + public: + ConnectCallbackWrapper(CompletionCallback* user_callback) + : ALLOW_THIS_IN_INITIALIZER_LIST( + CompletionCallbackImpl<ConnectCallbackWrapper>(this, + &ConnectCallbackWrapper::ReturnValueWrapper)), + user_callback_(user_callback) { + } + + private: + void ReturnValueWrapper(int rv) { + user_callback_->Run(rv > OK ? OK : rv); + delete this; + } + + CompletionCallback* user_callback_; +}; + int SSLClientSocketNSS::Connect(CompletionCallback* callback) { EnterFunction(""); DCHECK(transport_.get()); @@ -138,28 +167,38 @@ int SSLClientSocketNSS::Connect(CompletionCallback* callback) { GotoState(STATE_CONNECT); int rv = DoLoop(OK); if (rv == ERR_IO_PENDING) - user_callback_ = callback; + user_callback_ = new ConnectCallbackWrapper(callback); LeaveFunction(""); - return rv; + return rv > OK ? OK : rv; } -int SSLClientSocketNSS::ReconnectIgnoringLastError( - CompletionCallback* callback) { - EnterFunction(""); - // TODO(darin): implement me! - LeaveFunction(""); - return ERR_FAILED; +void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { + if (UpdateServerCert() != NULL && + ssl_config_.allowed_bad_certs_.count(server_cert_)) { + SSL_InvalidateSession(nss_fd_); + } } void SSLClientSocketNSS::Disconnect() { EnterFunction(""); + + // Reset object state + transport_send_busy_ = false; + transport_recv_busy_ = false; + user_buf_ = NULL; + user_buf_len_ = 0; + server_cert_error_ = OK; + completed_handshake_ = false; + nss_bufs_ = NULL; + // TODO(wtc): Send SSL close_notify alert. if (nss_fd_ != NULL) { + InvalidateSessionIfBadCertificate(); PR_Close(nss_fd_); nss_fd_ = NULL; } - completed_handshake_ = false; + transport_->Disconnect(); LeaveFunction(""); } @@ -229,6 +268,20 @@ int SSLClientSocketNSS::Write(const char* buf, int buf_len, return rv; } +X509Certificate *SSLClientSocketNSS::UpdateServerCert() { + // We set the server_cert_ from OwnAuthCertHandler(), but this handler + // does not necessarily get called if we are continuing a cached SSL + // session. + if (server_cert_ == NULL) { + X509Certificate::OSCertHandle nss_cert = SSL_PeerCertificate(nss_fd_); + if (nss_cert) { + server_cert_ = X509Certificate::CreateFromHandle( + nss_cert, X509Certificate::SOURCE_FROM_NETWORK); + } + } + return server_cert_; +} + void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { EnterFunction(""); ssl_info->Reset(); @@ -248,13 +301,12 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() << " for cipherSuite " << channel_info.cipherSuite; } + UpdateServerCert(); } if (server_cert_error_ != net::OK) ssl_info->SetCertError(server_cert_error_); - X509Certificate::OSCertHandle nss_cert = SSL_PeerCertificate(nss_fd_); - if (nss_cert) - ssl_info->cert = X509Certificate::CreateFromHandle(nss_cert, - X509Certificate::SOURCE_FROM_NETWORK); + DCHECK(server_cert_ != NULL); + ssl_info->cert = server_cert_; LeaveFunction(""); } @@ -355,7 +407,6 @@ void SSLClientSocketNSS::BufferRecvComplete(int result) { LeaveFunction(""); } - int SSLClientSocketNSS::DoLoop(int last_io_result) { EnterFunction(last_io_result); bool network_moved; @@ -409,20 +460,49 @@ int SSLClientSocketNSS::DoLoop(int last_io_result) { int SSLClientSocketNSS::DoConnect() { EnterFunction(""); GotoState(STATE_CONNECT_COMPLETE); - return transport_->Connect(&io_callback_); + + // The caller has to make sure that the transport socket is connected. If + // it isn't, we will eventually fail when trying to negotiate an SSL session. + // But we cannot call transport_->Connect(), as we do not know if there is + // any proxy negotiation that needs to be performed prior to establishing + // the SSL session. + return OK; +} + +// static +// NSS calls this if an incoming certificate needs to be verified. +SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, + PRFileDesc* socket, + PRBool checksig, + PRBool is_server) { + SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); + + // Remember the certificate as it will no longer be accessible if the + // handshake fails. + that->UpdateServerCert(); + + return SSL_AuthCertificate(CERT_GetDefaultCertDB(), socket, checksig, + is_server); } // static // NSS calls this if an incoming certificate is invalid. -SECStatus SSLClientSocketNSS::OwnBadCertHandler(void* arg, PRFileDesc* socket) { +SECStatus SSLClientSocketNSS::OwnBadCertHandler(void* arg, + PRFileDesc* socket) { SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); + + if (that->server_cert_ && + that->ssl_config_.allowed_bad_certs_.count(that->server_cert_)) { + LOG(INFO) << "accepting bad SSL certificate, as user told us to"; + + return SECSuccess; + } PRErrorCode prerr = PR_GetError(); that->server_cert_error_ = NetErrorFromNSPRError(prerr); LOG(INFO) << "server certificate is invalid; NSS error code " << prerr << ", net error " << that->server_cert_error_; - // Return SECSuccess to override the problem. - // Chromium wants it to succeed here, and may abort the connection later. - return SECSuccess; + + return SECFailure; } int SSLClientSocketNSS::DoConnectComplete(int result) { @@ -503,6 +583,10 @@ int SSLClientSocketNSS::DoConnectComplete(int result) { if (rv != SECSuccess) return ERR_UNEXPECTED; + rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); + if (rv != SECSuccess) + return ERR_UNEXPECTED; + rv = SSL_BadCertHook(nss_fd_, OwnBadCertHandler, this); if (rv != SECSuccess) return ERR_UNEXPECTED; @@ -520,11 +604,14 @@ int SSLClientSocketNSS::DoConnectComplete(int result) { int SSLClientSocketNSS::DoHandshakeRead() { EnterFunction(""); - int net_error; + int net_error = net::OK; int rv = SSL_ForceHandshake(nss_fd_); if (rv == SECSuccess) { - net_error = server_cert_error_; + DCHECK(server_cert_error_ == net::OK); + + InvalidateSessionIfBadCertificate(); + // there's a callback for this, too completed_handshake_ = true; // Done! diff --git a/net/base/ssl_client_socket_nss.h b/net/base/ssl_client_socket_nss.h index 9b77f94..89fe99e 100644 --- a/net/base/ssl_client_socket_nss.h +++ b/net/base/ssl_client_socket_nss.h @@ -17,6 +17,8 @@ namespace net { +class X509Certificate; + // An SSL client socket implemented with Mozilla NSS. class SSLClientSocketNSS : public SSLClientSocket { public: @@ -34,7 +36,6 @@ class SSLClientSocketNSS : public SSLClientSocket { // ClientSocket methods: virtual int Connect(CompletionCallback* callback); - virtual int ReconnectIgnoringLastError(CompletionCallback* callback); virtual void Disconnect(); virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; @@ -44,6 +45,8 @@ class SSLClientSocketNSS : public SSLClientSocket { virtual int Write(const char* buf, int buf_len, CompletionCallback* callback); private: + void InvalidateSessionIfBadCertificate(); + X509Certificate* UpdateServerCert(); void DoCallback(int result); void OnIOComplete(int result); @@ -59,7 +62,12 @@ class SSLClientSocketNSS : public SSLClientSocket { void BufferSendComplete(int result); void BufferRecvComplete(int result); - // nss calls this on error. We pass 'this' as the first argument. + // NSS calls this when checking certificates. We pass 'this' as the first + // argument. + static SECStatus OwnAuthCertHandler(void* arg, PRFileDesc* socket, + PRBool checksig, PRBool is_server); + + // NSS calls this on error. We pass 'this' as the first argument. static SECStatus OwnBadCertHandler(void* arg, PRFileDesc* socket); CompletionCallbackImpl<SSLClientSocketNSS> buffer_send_callback_; @@ -81,6 +89,9 @@ class SSLClientSocketNSS : public SSLClientSocket { // Set when handshake finishes. Value is net error code, see net_errors.h int server_cert_error_; + // Set during handshake. + scoped_refptr<X509Certificate> server_cert_; + bool completed_handshake_; enum State { diff --git a/net/base/ssl_client_socket_unittest.cc b/net/base/ssl_client_socket_unittest.cc index 7b551fe..7c7b170 100644 --- a/net/base/ssl_client_socket_unittest.cc +++ b/net/base/ssl_client_socket_unittest.cc @@ -79,8 +79,14 @@ TEST_F(SSLClientSocketTest, MAYBE_Connect) { &addr, NULL); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kHostName, kDefaultSSLConfig)); EXPECT_FALSE(sock->IsConnected()); @@ -111,8 +117,14 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectExpired) { &addr, NULL); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kHostName, kDefaultSSLConfig)); EXPECT_FALSE(sock->IsConnected()); @@ -126,7 +138,9 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectExpired) { EXPECT_EQ(net::ERR_CERT_DATE_INVALID, rv); } - EXPECT_TRUE(sock->IsConnected()); + // We cannot test sock->IsConnected(), as the NSS implementation disconnects + // the socket when it encounters an error, whereas other implementations + // leave it connected. } TEST_F(SSLClientSocketTest, MAYBE_ConnectMismatched) { @@ -140,8 +154,14 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectMismatched) { &addr, NULL); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kMismatchedHostName, kDefaultSSLConfig)); EXPECT_FALSE(sock->IsConnected()); @@ -155,13 +175,9 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectMismatched) { EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, rv); } - // The Windows code happens to keep the connection - // open now in spite of an error. The designers of - // this API intended to also allow the connection - // to be closed on error, in which case the caller - // should call ReconnectIgnoringLastError, but - // that's currently unimplemented. - EXPECT_TRUE(sock->IsConnected()); + // We cannot test sock->IsConnected(), as the NSS implementation disconnects + // the socket when it encounters an error, whereas other implementations + // leave it connected. } // TODO(wtc): Add unit tests for IsConnectedAndIdle: @@ -183,8 +199,14 @@ TEST_F(SSLClientSocketTest, MAYBE_Read) { rv = callback.WaitForResult(); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kHostName, kDefaultSSLConfig)); @@ -231,8 +253,14 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_SmallChunks) { &addr, NULL); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kHostName, kDefaultSSLConfig)); rv = sock->Connect(&callback); @@ -277,8 +305,14 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_Interrupted) { &addr, NULL); EXPECT_EQ(net::OK, rv); + net::ClientSocket *transport = new net::TCPClientSocket(addr); + rv = transport->Connect(&callback); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + scoped_ptr<net::SSLClientSocket> sock( - socket_factory_->CreateSSLClientSocket(new net::TCPClientSocket(addr), + socket_factory_->CreateSSLClientSocket(transport, server_.kHostName, kDefaultSSLConfig)); rv = sock->Connect(&callback); diff --git a/net/base/ssl_client_socket_win.cc b/net/base/ssl_client_socket_win.cc index 96484fa..70ef6a5 100644 --- a/net/base/ssl_client_socket_win.cc +++ b/net/base/ssl_client_socket_win.cc @@ -280,12 +280,6 @@ int SSLClientSocketWin::Connect(CompletionCallback* callback) { return rv; } -int SSLClientSocketWin::ReconnectIgnoringLastError( - CompletionCallback* callback) { - // TODO(darin): implement me! - return ERR_FAILED; -} - void SSLClientSocketWin::Disconnect() { // TODO(wtc): Send SSL close_notify alert. completed_handshake_ = false; @@ -450,7 +444,13 @@ int SSLClientSocketWin::DoLoop(int last_io_result) { int SSLClientSocketWin::DoConnect() { next_state_ = STATE_CONNECT_COMPLETE; - return transport_->Connect(&io_callback_); + + // The caller has to make sure that the transport socket is connected. If + // it isn't, we will eventually fail when trying to negotiate an SSL session. + // But we cannot call transport_->Connect(), as we do not know if there is + // any proxy negotiation that needs to be performed prior to establishing + // the SSL session. + return OK; } int SSLClientSocketWin::DoConnectComplete(int result) { diff --git a/net/base/ssl_client_socket_win.h b/net/base/ssl_client_socket_win.h index 68eb24d..a3935f6 100644 --- a/net/base/ssl_client_socket_win.h +++ b/net/base/ssl_client_socket_win.h @@ -39,7 +39,6 @@ class SSLClientSocketWin : public SSLClientSocket { // ClientSocket methods: virtual int Connect(CompletionCallback* callback); - virtual int ReconnectIgnoringLastError(CompletionCallback* callback); virtual void Disconnect(); virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h index 96d42a2..dec6fdb 100644 --- a/net/base/ssl_config_service.h +++ b/net/base/ssl_config_service.h @@ -5,7 +5,10 @@ #ifndef NET_BASE_SSL_CONFIG_SERVICE_H__ #define NET_BASE_SSL_CONFIG_SERVICE_H__ +#include <set> + #include "base/time.h" +#include "net/base/x509_certificate.h" namespace net { @@ -23,6 +26,12 @@ struct SSLConfig { bool ssl2_enabled; // True if SSL 2.0 is enabled. bool ssl3_enabled; // True if SSL 3.0 is enabled. bool tls1_enabled; // True if TLS 1.0 is enabled. + + // Add any known-bad SSL certificates to allowed_bad_certs_ that should not + // trigger an ERR_CERT_*_INVALID error when calling SSLClientSocket::Connect. + // This would normally be done in response to the user explicitly accepting + // the bad certificate. + std::set<scoped_refptr<X509Certificate> > allowed_bad_certs_; }; // This class is responsible for getting and setting the SSL configuration. diff --git a/net/base/tcp_client_socket.h b/net/base/tcp_client_socket.h index b846836..729bbbc 100644 --- a/net/base/tcp_client_socket.h +++ b/net/base/tcp_client_socket.h @@ -46,7 +46,6 @@ class TCPClientSocket : public ClientSocket, // ClientSocket methods: virtual int Connect(CompletionCallback* callback); - virtual int ReconnectIgnoringLastError(CompletionCallback* callback); virtual void Disconnect(); virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; diff --git a/net/base/tcp_client_socket_libevent.cc b/net/base/tcp_client_socket_libevent.cc index 204b700..8d51dbf 100644 --- a/net/base/tcp_client_socket_libevent.cc +++ b/net/base/tcp_client_socket_libevent.cc @@ -126,11 +126,6 @@ int TCPClientSocket::Connect(CompletionCallback* callback) { return ERR_IO_PENDING; } -int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { - // No ignorable errors! - return ERR_UNEXPECTED; -} - void TCPClientSocket::Disconnect() { if (socket_ == kInvalidSocket) return; diff --git a/net/base/tcp_client_socket_win.cc b/net/base/tcp_client_socket_win.cc index 7c10d2d..9d69505 100644 --- a/net/base/tcp_client_socket_win.cc +++ b/net/base/tcp_client_socket_win.cc @@ -106,11 +106,6 @@ int TCPClientSocket::Connect(CompletionCallback* callback) { return ERR_IO_PENDING; } -int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { - // No ignorable errors! - return ERR_UNEXPECTED; -} - void TCPClientSocket::Disconnect() { if (socket_ == INVALID_SOCKET) return; |