1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/tcp_client_socket_win.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <mstcpip.h> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/memory_debug.h" 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/stats_counters.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/sys_info.h" 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/object_watcher.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/address_list_net_log_param.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/connection_type_histograms.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/ip_endpoint.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h" 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/network_change_notifier.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/sys_addrinfo.h" 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/winsock_init.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/winsock_util.h" 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapConnectError(int os_error) { 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (os_error) { 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // connect fails with WSAEACCES when Windows Firewall blocks the 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // connection. 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case WSAEACCES: 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return ERR_NETWORK_ACCESS_DENIED; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case WSAETIMEDOUT: 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_TIMED_OUT; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: { 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int net_error = MapSystemError(os_error); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (net_error == ERR_FAILED) 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Give a more specific error when the user is offline. 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (net_error == ERR_ADDRESS_UNREACHABLE && 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NetworkChangeNotifier::IsOffline()) { 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_INTERNET_DISCONNECTED; 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net_error; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//----------------------------------------------------------------------------- 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class encapsulates all the state that has to be preserved as long as 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// there is a network IO operation in progress. If the owner TCPClientSocketWin 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is destroyed while an operation is in progress, the Core is detached and it 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// lives until the operation completes and the OS doesn't reference any resource 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// declared on this class anymore. 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass TCPClientSocketWin::Core : public base::RefCounted<Core> { 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit Core(TCPClientSocketWin* socket); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Start watching for the end of a read or write operation. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void WatchForRead(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void WatchForWrite(); 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The TCPClientSocketWin is going away. 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Detach() { socket_ = NULL; } 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The separate OVERLAPPED variables for asynchronous operation. 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |read_overlapped_| is used for both Connect() and Read(). 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |write_overlapped_| is only used for Write(); 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OVERLAPPED read_overlapped_; 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OVERLAPPED write_overlapped_; 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The buffers used in Read() and Write(). 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSABUF read_buffer_; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSABUF write_buffer_; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<IOBuffer> read_iobuffer_; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<IOBuffer> write_iobuffer_; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int write_buffer_length_; 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Throttle the read size based on our current slow start state. 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns the throttled read size. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int ThrottleReadSize(int size) { 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (slow_start_throttle_ < kMaxSlowStartThrottle) { 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size = std::min(size, slow_start_throttle_); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott slow_start_throttle_ *= 2; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return size; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class base::RefCounted<Core>; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen class ReadDelegate : public base::win::ObjectWatcher::Delegate { 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit ReadDelegate(Core* core) : core_(core) {} 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~ReadDelegate() {} 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // base::ObjectWatcher::Delegate methods: 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnObjectSignaled(HANDLE object); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Core* const core_; 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen class WriteDelegate : public base::win::ObjectWatcher::Delegate { 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit WriteDelegate(Core* core) : core_(core) {} 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~WriteDelegate() {} 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // base::ObjectWatcher::Delegate methods: 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnObjectSignaled(HANDLE object); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Core* const core_; 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~Core(); 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The socket that created this object. 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TCPClientSocketWin* socket_; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |reader_| handles the signals from |read_watcher_|. 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReadDelegate reader_; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |writer_| handles the signals from |write_watcher_|. 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WriteDelegate writer_; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |read_watcher_| watches for events from Connect() and Read(). 1373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ObjectWatcher read_watcher_; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |write_watcher_| watches for events from Write(); 1393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ObjectWatcher write_watcher_; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // When doing reads from the socket, we try to mirror TCP's slow start. 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We do this because otherwise the async IO subsystem artifically delays 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // returning data to the application. 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const int kInitialSlowStartThrottle = 1 * 1024; 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const int kMaxSlowStartThrottle = 32 * kInitialSlowStartThrottle; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int slow_start_throttle_; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(Core); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTCPClientSocketWin::Core::Core( 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TCPClientSocketWin* socket) 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : write_buffer_length_(0), 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_(socket), 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST(reader_(this)), 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)), 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott slow_start_throttle_(kInitialSlowStartThrottle) { 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&read_overlapped_, 0, sizeof(read_overlapped_)); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&write_overlapped_, 0, sizeof(write_overlapped_)); 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTCPClientSocketWin::Core::~Core() { 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure the message loop is not watching this object anymore. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_watcher_.StopWatching(); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_watcher_.StopWatching(); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSACloseEvent(read_overlapped_.hEvent); 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSACloseEvent(write_overlapped_.hEvent); 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::Core::WatchForRead() { 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We grab an extra reference because there is an IO operation in progress. 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Balanced in ReadDelegate::OnObjectSignaled(). 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddRef(); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::Core::WatchForWrite() { 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We grab an extra reference because there is an IO operation in progress. 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Balanced in WriteDelegate::OnObjectSignaled(). 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddRef(); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled( 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HANDLE object) { 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(object, core_->read_overlapped_.hEvent); 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (core_->socket_) { 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (core_->socket_->waiting_connect()) { 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->socket_->DidCompleteConnect(); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->socket_->DidCompleteRead(); 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->Release(); 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled( 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HANDLE object) { 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(object, core_->write_overlapped_.hEvent); 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (core_->socket_) 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->socket_->DidCompleteWrite(); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->Release(); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//----------------------------------------------------------------------------- 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTCPClientSocketWin::TCPClientSocketWin(const AddressList& addresses, 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::NetLog* net_log, 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const net::NetLog::Source& source) 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : socket_(INVALID_SOCKET), 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott addresses_(addresses), 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_ai_(NULL), 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_read_(false), 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_write_(false), 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_callback_(NULL), 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch write_callback_(NULL), 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_connect_state_(CONNECT_STATE_NONE), 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connect_os_error_(0), 224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), 225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch previously_disconnected_(false) { 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_refptr<NetLog::EventParameters> params; 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (source.is_valid()) 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick params = new NetLogSourceParameter("source_dependency", source); 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnsureWinsockInit(); 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTCPClientSocketWin::~TCPClientSocketWin() { 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Disconnect(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid TCPClientSocketWin::AdoptSocket(SOCKET socket) { 2394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DCHECK_EQ(socket_, INVALID_SOCKET); 2404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch socket_ = socket; 2414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int error = SetupSocket(); 2424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DCHECK_EQ(0, error); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen core_ = new Core(this); 2444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch current_ai_ = addresses_.head(); 2454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch use_history_.set_was_ever_connected(); 2464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 2474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2487b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 2497b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true 2507b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests) 2517b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 2527b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint TCPClientSocketWin::Connect(CompletionCallback* callback 2537b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 2547b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 2557b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 2567b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If already connected, then just return OK. 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socket_ != INVALID_SOCKET) 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter connects("tcp.connect"); 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connects.Increment(); 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new AddressListNetLogParam(addresses_)); 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will try to connect to each address in addresses_. Start with the 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first one in the list. 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_connect_state_ = CONNECT_STATE_CONNECT; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_ai_ = addresses_.head(); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = DoConnectLoop(OK); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Synchronous operation not supported. 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_callback_ = callback; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogConnectCompletion(rv); 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketWin::DoConnectLoop(int result) { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = result; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectState state = next_connect_state_; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_connect_state_ = CONNECT_STATE_NONE; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state) { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CONNECT_STATE_CONNECT: 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(OK, rv); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoConnect(); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CONNECT_STATE_CONNECT_COMPLETE: 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoConnectComplete(rv); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(DFATAL) << "bad state " << state; 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = ERR_UNEXPECTED; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketWin::DoConnect() { 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const struct addrinfo* ai = current_ai_; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(ai); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0, connect_os_error_); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (previously_disconnected_) { 317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch use_history_.Reset(); 318513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch previously_disconnected_ = false; 319513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new NetLogStringParameter( 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "address", NetAddressToStringWithPort(current_ai_))); 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connect_os_error_ = CreateSocket(ai); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (connect_os_error_ != 0) 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(connect_os_error_); 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!core_); 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_ = new Core(this); 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // WSACreateEvent creates a manual-reset event object. 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->read_overlapped_.hEvent = WSACreateEvent(); 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // WSAEventSelect sets the socket to non-blocking mode as a side effect. 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Our connect() and recv() calls require that the socket be non-blocking. 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->write_overlapped_.hEvent = WSACreateEvent(); 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Connected without waiting! 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The MSDN page for connect says: 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // With a nonblocking socket, the connection attempt cannot be completed 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // immediately. In this case, connect will return SOCKET_ERROR, and 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // WSAGetLastError will return WSAEWOULDBLOCK. 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // which implies that for a nonblocking socket, connect never returns 0. 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It's not documented whether the event object will be signaled or not 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if connect does return 0. So the code below is essentially dead code 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // and we don't know if it's correct. 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int os_error = WSAGetLastError(); 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (os_error != WSAEWOULDBLOCK) { 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "connect failed: " << os_error; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connect_os_error_ = os_error; 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapConnectError(os_error); 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->WatchForRead(); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketWin::DoConnectComplete(int result) { 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Log the end of this attempt (and any OS error it threw). 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int os_error = connect_os_error_; 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connect_os_error_ = 0; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<NetLog::EventParameters> params; 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result != OK) 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch params = new NetLogIntegerParameter("os_error", os_error); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result == OK) { 3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_was_ever_connected(); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; // Done! 3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close whatever partially connected socket we currently have. 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoDisconnect(); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to fall back to the next address in the list. 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_ai_->ai_next) { 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_connect_state_ = CONNECT_STATE_CONNECT; 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_ai_ = current_ai_->ai_next; 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Otherwise there is nothing to fall back to, so give up. 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::Disconnect() { 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoDisconnect(); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_ai_ = NULL; 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketWin::DoDisconnect() { 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socket_ == INVALID_SOCKET) 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: don't use CancelIo to cancel pending IO because it doesn't work 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // when there is a Winsock layered service provider. 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In most socket implementations, closing a socket results in a graceful 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // connection shutdown, but in Winsock we have to call shutdown explicitly. 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See the MSDN page "Graceful Shutdown, Linger Options, and Socket Closure" 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // at http://msdn.microsoft.com/en-us/library/ms738547.aspx 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott shutdown(socket_, SD_SEND); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This cancels any pending IO. 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott closesocket(socket_); 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_ = INVALID_SOCKET; 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (waiting_connect()) { 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We closed the socket, so this notification will never come. 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // From MSDN' WSAEventSelect documentation: 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // "Closing a socket with closesocket also cancels the association and 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // selection of network events specified in WSAEventSelect for the socket". 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->Release(); 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_read_ = false; 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_write_ = false; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->Detach(); 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_ = NULL; 435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 436513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch previously_disconnected_ = true; 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketWin::IsConnected() const { 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_ == INVALID_SOCKET || waiting_connect()) 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if connection is alive. 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char c; 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = recv(socket_, &c, 1, MSG_PEEK); 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == 0) 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketWin::IsConnectedAndIdle() const { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_ == INVALID_SOCKET || waiting_connect()) 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if connection is alive and we haven't received any data 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // unexpectedly. 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char c; 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = recv(socket_, &c, 1, MSG_PEEK); 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv >= 0) 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (WSAGetLastError() != WSAEWOULDBLOCK) 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketWin::GetPeerAddress(AddressList* address) const { 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(address); 4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!IsConnected()) 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SOCKET_NOT_CONNECTED; 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch address->Copy(current_ai_, false); 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPClientSocketWin::GetLocalAddress(IPEndPoint* address) const { 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(address); 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsConnected()) 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_SOCKET_NOT_CONNECTED; 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr_storage addr_storage; 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socklen_t addr_len = sizeof(addr_storage); 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (getsockname(socket_, addr, &addr_len)) 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(WSAGetLastError()); 494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!address->FromSockAddr(addr, addr_len)) 495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_FAILED; 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return OK; 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketWin::SetSubresourceSpeculation() { 5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_subresource_speculation(); 5013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketWin::SetOmniboxSpeculation() { 5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_omnibox_speculation(); 5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TCPClientSocketWin::WasEverUsed() const { 5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return use_history_.was_used_to_convey_data(); 5093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 511513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool TCPClientSocketWin::UsingTCPFastOpen() const { 512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Not supported on windows. 513513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 514513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 515513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketWin::Read(IOBuffer* buf, 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len, 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(socket_, INVALID_SOCKET); 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!waiting_read_); 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!read_callback_); 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!core_->read_iobuffer_); 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len = core_->ThrottleReadSize(buf_len); 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->read_buffer_.len = buf_len; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->read_buffer_.buf = buf->data(); 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(wtc): Remove the assertion after enough testing. 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AssertEventNotSignaled(core_->read_overlapped_.hEvent); 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD num, flags = 0; 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = WSARecv(socket_, &core_->read_buffer_, 1, &num, &flags, 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &core_->read_overlapped_, NULL); 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == 0) { 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Because of how WSARecv fills memory when used asynchronously, Purify 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // isn't able to detect that it's been initialized, so it scans for 0xcd 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in the buffer and reports UMRs (uninitialized memory reads) for those 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // individual bytes. We override that in PURIFY builds to avoid the 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // false error reports. 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See bug 5297. 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num); 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter read_bytes("tcp.read_bytes"); 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_bytes.Add(num); 5463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (num > 0) 5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_was_used_to_convey_data(); 548731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, num, 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick core_->read_buffer_.buf); 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return static_cast<int>(num); 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int os_error = WSAGetLastError(); 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (os_error != WSA_IO_PENDING) 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(os_error); 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->WatchForRead(); 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_read_ = true; 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_callback_ = callback; 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->read_iobuffer_ = buf; 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketWin::Write(IOBuffer* buf, 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len, 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(socket_, INVALID_SOCKET); 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!waiting_write_); 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!write_callback_); 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(buf_len, 0); 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!core_->write_iobuffer_); 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter writes("tcp.writes"); 5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick writes.Increment(); 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->write_buffer_.len = buf_len; 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->write_buffer_.buf = buf->data(); 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_->write_buffer_length_ = buf_len; 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(wtc): Remove the assertion after enough testing. 5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AssertEventNotSignaled(core_->write_overlapped_.hEvent); 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD num; 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &core_->write_overlapped_, NULL); 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == 0) { 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = static_cast<int>(num); 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv > buf_len || rv < 0) { 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It seems that some winsock interceptors report that more was written 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than was available. Treat this as an error. http://crbug.com/27870 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " bytes, but " << rv << " bytes reported."; 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter write_bytes("tcp.write_bytes"); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch write_bytes.Add(rv); 5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rv > 0) 5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_was_used_to_convey_data(); 600731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, rv, 601731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick core_->write_buffer_.buf); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int os_error = WSAGetLastError(); 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (os_error != WSA_IO_PENDING) 607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return MapSystemError(os_error); 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->WatchForWrite(); 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_write_ = true; 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_callback_ = callback; 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->write_iobuffer_ = buf; 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketWin::SetReceiveBufferSize(int32 size) { 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<const char*>(&size), sizeof(size)); 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError(); 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv == 0; 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketWin::SetSendBufferSize(int32 size) { 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<const char*>(&size), sizeof(size)); 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError(); 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv == 0; 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketWin::CreateSocket(const struct addrinfo* ai) { 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSA_FLAG_OVERLAPPED); 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socket_ == INVALID_SOCKET) { 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int os_error = WSAGetLastError(); 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "WSASocket failed: " << os_error; 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return os_error; 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 6404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return SetupSocket(); 6414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint TCPClientSocketWin::SetupSocket() { 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Increase the socket buffer sizes from the default sizes for WinXP. In 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // performance testing, there is substantial benefit by increasing from 8KB 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to 64KB. 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See also: 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://support.microsoft.com/kb/823764/EN-US 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // On Vista, if we manually set these sizes, Vista turns off its receive 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // window auto-tuning feature. 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since Vista's auto-tune is better than any static value we can could set, 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // only change these on pre-vista machines. 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32 major_version, minor_version, fix_version; 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &fix_version); 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (major_version < 6) { 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int32 kSocketBufferSize = 64 * 1024; 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetReceiveBufferSize(kSocketBufferSize); 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetSendBufferSize(kSocketBufferSize); 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Disable Nagle. 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The Nagle implementation on windows is governed by RFC 896. The idea 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // behind Nagle is to reduce small packets on the network. When Nagle is 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // enabled, if a partial packet has been sent, the TCP stack will disallow 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // further *partial* packets until an ACK has been received from the other 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // side. Good applications should always strive to send as much data as 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // possible and avoid partial-packet sends. However, in most real world 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // applications, there are edge cases where this does not happen, and two 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // partil packets may be sent back to back. For a browser, it is NEVER 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a benefit to delay for an RTT before the second packet is sent. 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // As a practical example in Chromium today, consider the case of a small 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // POST. I have verified this: 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Client writes 649 bytes of header (partial packet #1) 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Client writes 50 bytes of POST data (partial packet #2) 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In the above example, with Nagle, a RTT delay is inserted between these 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // two sends due to nagle. RTTs can easily be 100ms or more. The best 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // fix is to make sure that for POSTing data, we write as much data as 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // possible and minimize partial packets. We will fix that. But disabling 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Nagle also ensure we don't run into this delay in other edge cases. 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See also: 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://technet.microsoft.com/en-us/library/bb726981.aspx 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const BOOL kDisableNagle = TRUE; 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, 68772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const char*>(&kDisableNagle), 68872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sizeof(kDisableNagle)); 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!rv) << "Could not disable nagle"; 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP 69272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // connections. See http://crbug.com/27400 for details. 69372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 69472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen struct tcp_keepalive keepalive_vals = { 69572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1, // TCP keep-alive on. 69672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45000, // Wait 45s until sending first TCP keep-alive packet. 69772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45000, // Wait 45s between sending TCP keep-alive packets. 69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 69972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DWORD bytes_returned = 0xABAB; 70072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = WSAIoctl(socket_, SIO_KEEPALIVE_VALS, &keepalive_vals, 70172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sizeof(keepalive_vals), NULL, 0, 70272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &bytes_returned, NULL, NULL); 70372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket_ 70472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " [error: " << WSAGetLastError() << "]."; 70572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 70672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Disregard any failure in disabling nagle or enabling TCP Keep-Alive. 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketWin::LogConnectCompletion(int net_error) { 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (net_error == OK) 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateConnectionTypeHistograms(CONNECTION_ANY); 71372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 71472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (net_error != OK) { 71572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 71672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 71772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 71872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 71972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen struct sockaddr_storage source_address; 72072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen socklen_t addrlen = sizeof(source_address); 72172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = getsockname( 72272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen); 72372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != 0) { 72472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "getsockname() [rv: " << rv 72572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << "] error: " << WSAGetLastError(); 72672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 72772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 72872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 72972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 73072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 73172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string source_address_str = 73272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetAddressToStringWithPort( 73372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const struct sockaddr*>(&source_address), 73472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sizeof(source_address)); 73572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 73672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new NetLogStringParameter( 73772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "source address", 73872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen source_address_str))); 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::DoReadCallback(int rv) { 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(rv, ERR_IO_PENDING); 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(read_callback_); 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // since Run may result in Read being called, clear read_callback_ up front. 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = read_callback_; 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_callback_ = NULL; 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv); 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::DoWriteCallback(int rv) { 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(rv, ERR_IO_PENDING); 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(write_callback_); 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // since Run may result in Write being called, clear write_callback_ up front. 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = write_callback_; 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_callback_ = NULL; 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv); 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::DidCompleteConnect() { 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result; 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSANETWORKEVENTS events; 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &events); 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int os_error = 0; 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == SOCKET_ERROR) { 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch os_error = WSAGetLastError(); 772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = MapSystemError(os_error); 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (events.lNetworkEvents & FD_CONNECT) { 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch os_error = events.iErrorCode[FD_CONNECT_BIT]; 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = MapConnectError(os_error); 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_UNEXPECTED; 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connect_os_error_ = os_error; 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoConnectLoop(result); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != ERR_IO_PENDING) { 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogConnectCompletion(rv); 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoReadCallback(rv); 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::DidCompleteRead() { 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(waiting_read_); 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD num_bytes, flags; 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &num_bytes, FALSE, &flags); 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSAResetEvent(core_->read_overlapped_.hEvent); 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_read_ = false; 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->read_iobuffer_ = NULL; 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ok) { 798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter read_bytes("tcp.read_bytes"); 7993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick read_bytes.Add(num_bytes); 8003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (num_bytes > 0) 8013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_was_used_to_convey_data(); 802731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, num_bytes, 803731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick core_->read_buffer_.buf); 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 805ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoReadCallback(ok ? num_bytes : MapSystemError(WSAGetLastError())); 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketWin::DidCompleteWrite() { 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(waiting_write_); 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD num_bytes, flags; 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &num_bytes, FALSE, &flags); 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WSAResetEvent(core_->write_overlapped_.hEvent); 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waiting_write_ = false; 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv; 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ok) { 818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rv = MapSystemError(WSAGetLastError()); 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = static_cast<int>(num_bytes); 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv > core_->write_buffer_length_ || rv < 0) { 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It seems that some winsock interceptors report that more was written 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than was available. Treat this as an error. http://crbug.com/27870 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Detected broken LSP: Asked to write " 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << core_->write_buffer_length_ << " bytes, but " << rv 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " bytes reported."; 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 829ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter write_bytes("tcp.write_bytes"); 8303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick write_bytes.Add(num_bytes); 8313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (num_bytes > 0) 8323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_history_.set_was_used_to_convey_data(); 833731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes, 834731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick core_->write_buffer_.buf); 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott core_->write_iobuffer_ = NULL; 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoWriteCallback(rv); 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 842