158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/socket/tcp_socket.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/socket/tcp_socket_win.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mstcpip.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/callback_helpers.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/logging.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/stats_counters.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/win/windows_version.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/address_list.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/connection_type_histograms.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/io_buffer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/network_change_notifier.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_util.h" 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/socket_descriptor.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_net_log_params.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const int kTCPKeepAliveSeconds = 45; 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SetSocketReceiveBufferSize(SOCKET socket, int32 size) { 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) reinterpret_cast<const char*>(&size), sizeof(size)); 35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError()); 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error; 37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return net_error; 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SetSocketSendBufferSize(SOCKET socket, int32 size) { 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) reinterpret_cast<const char*>(&size), sizeof(size)); 43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError()); 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!rv) << "Could not set socket send buffer size: " << net_error; 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return net_error; 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Disable Nagle. 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// The Nagle implementation on windows is governed by RFC 896. The idea 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// behind Nagle is to reduce small packets on the network. When Nagle is 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// enabled, if a partial packet has been sent, the TCP stack will disallow 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// further *partial* packets until an ACK has been received from the other 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// side. Good applications should always strive to send as much data as 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// possible and avoid partial-packet sends. However, in most real world 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// applications, there are edge cases where this does not happen, and two 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// partial packets may be sent back to back. For a browser, it is NEVER 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// a benefit to delay for an RTT before the second packet is sent. 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// As a practical example in Chromium today, consider the case of a small 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// POST. I have verified this: 61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Client writes 649 bytes of header (partial packet #1) 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Client writes 50 bytes of POST data (partial packet #2) 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// In the above example, with Nagle, a RTT delay is inserted between these 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// two sends due to nagle. RTTs can easily be 100ms or more. The best 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// fix is to make sure that for POSTing data, we write as much data as 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// possible and minimize partial packets. We will fix that. But disabling 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Nagle also ensure we don't run into this delay in other edge cases. 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// See also: 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// http://technet.microsoft.com/en-us/library/bb726981.aspx 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool DisableNagle(SOCKET socket, bool disable) { 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BOOL val = disable ? TRUE : FALSE; 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) reinterpret_cast<const char*>(&val), 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sizeof(val)); 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!rv) << "Could not disable nagle"; 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv == 0; 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Enable TCP Keep-Alive to prevent NAT routers from timing out TCP 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// connections. See http://crbug.com/27400 for details. 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int delay = delay_secs * 1000; 83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) struct tcp_keepalive keepalive_vals = { 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enable ? 1 : 0, // TCP keep-alive on. 85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delay, // Delay seconds before sending first TCP keep-alive packet. 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delay, // Delay seconds between sending TCP keep-alive packets. 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) }; 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DWORD bytes_returned = 0xABAB; 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &keepalive_vals, 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sizeof(keepalive_vals), NULL, 0, 91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &bytes_returned, NULL, NULL); 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << " [error: " << WSAGetLastError() << "]."; 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Disregard any failure in disabling nagle or enabling TCP Keep-Alive. 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv == 0; 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int MapConnectError(int os_error) { 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) switch (os_error) { 101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // connect fails with WSAEACCES when Windows Firewall blocks the 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // connection. 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case WSAEACCES: 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_NETWORK_ACCESS_DENIED; 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case WSAETIMEDOUT: 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_CONNECTION_TIMED_OUT; 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default: { 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int net_error = MapSystemError(os_error); 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (net_error == ERR_FAILED) 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Give a more specific error when the user is offline. 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (net_error == ERR_ADDRESS_UNREACHABLE && 114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NetworkChangeNotifier::IsOffline()) { 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_INTERNET_DISCONNECTED; 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return net_error; 119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace 124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//----------------------------------------------------------------------------- 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Nothing to do for Windows since it doesn't support TCP FastOpen. 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(jri): Remove these along with the corresponding global variables. 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsTCPFastOpenSupported() { return false; } 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsTCPFastOpenUserEnabled() { return false; } 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) {} 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This class encapsulates all the state that has to be preserved as long as 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// there is a network IO operation in progress. If the owner TCPSocketWin is 135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// destroyed while an operation is in progress, the Core is detached and it 136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// lives until the operation completes and the OS doesn't reference any resource 137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// declared on this class anymore. 138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class TCPSocketWin::Core : public base::RefCounted<Core> { 139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit Core(TCPSocketWin* socket); 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start watching for the end of a read or write operation. 143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void WatchForRead(); 144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void WatchForWrite(); 145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The TCPSocketWin is going away. 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void Detach() { socket_ = NULL; } 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The separate OVERLAPPED variables for asynchronous operation. 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |read_overlapped_| is used for both Connect() and Read(). 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |write_overlapped_| is only used for Write(); 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OVERLAPPED read_overlapped_; 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OVERLAPPED write_overlapped_; 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The buffers used in Read() and Write(). 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_refptr<IOBuffer> read_iobuffer_; 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_refptr<IOBuffer> write_iobuffer_; 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int read_buffer_length_; 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int write_buffer_length_; 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool non_blocking_reads_initialized_; 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) friend class base::RefCounted<Core>; 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) class ReadDelegate : public base::win::ObjectWatcher::Delegate { 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit ReadDelegate(Core* core) : core_(core) {} 169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~ReadDelegate() {} 170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // base::ObjectWatcher::Delegate methods: 172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnObjectSignaled(HANDLE object); 173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Core* const core_; 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) }; 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) class WriteDelegate : public base::win::ObjectWatcher::Delegate { 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit WriteDelegate(Core* core) : core_(core) {} 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~WriteDelegate() {} 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // base::ObjectWatcher::Delegate methods: 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnObjectSignaled(HANDLE object); 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Core* const core_; 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) }; 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ~Core(); 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The socket that created this object. 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) TCPSocketWin* socket_; 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |reader_| handles the signals from |read_watcher_|. 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ReadDelegate reader_; 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |writer_| handles the signals from |write_watcher_|. 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WriteDelegate writer_; 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |read_watcher_| watches for events from Connect() and Read(). 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::win::ObjectWatcher read_watcher_; 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |write_watcher_| watches for events from Write(); 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::win::ObjectWatcher write_watcher_; 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Core); 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TCPSocketWin::Core::Core(TCPSocketWin* socket) 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : read_buffer_length_(0), 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_buffer_length_(0), 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) non_blocking_reads_initialized_(false), 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) socket_(socket), 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) reader_(this), 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) writer_(this) { 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) memset(&read_overlapped_, 0, sizeof(read_overlapped_)); 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) memset(&write_overlapped_, 0, sizeof(write_overlapped_)); 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_overlapped_.hEvent = WSACreateEvent(); 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_overlapped_.hEvent = WSACreateEvent(); 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TCPSocketWin::Core::~Core() { 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Make sure the message loop is not watching this object anymore. 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_watcher_.StopWatching(); 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_watcher_.StopWatching(); 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSACloseEvent(read_overlapped_.hEvent); 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSACloseEvent(write_overlapped_.hEvent); 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::Core::WatchForRead() { 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We grab an extra reference because there is an IO operation in progress. 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Balanced in ReadDelegate::OnObjectSignaled(). 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AddRef(); 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::Core::WatchForWrite() { 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We grab an extra reference because there is an IO operation in progress. 242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Balanced in WriteDelegate::OnObjectSignaled(). 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AddRef(); 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(object, core_->read_overlapped_.hEvent); 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (core_->socket_) { 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (core_->socket_->waiting_connect_) 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->socket_->DidCompleteConnect(); 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->socket_->DidSignalRead(); 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->Release(); 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::Core::WriteDelegate::OnObjectSignaled( 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) HANDLE object) { 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(object, core_->write_overlapped_.hEvent); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (core_->socket_) 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->socket_->DidCompleteWrite(); 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->Release(); 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//----------------------------------------------------------------------------- 269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TCPSocketWin::TCPSocketWin(net::NetLog* net_log, 27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const net::NetLog::Source& source) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(INVALID_SOCKET), 273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_event_(WSA_INVALID_EVENT), 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_(NULL), 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accept_address_(NULL), 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_connect_(false), 277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_read_(false), 278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_write_(false), 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connect_os_error_(0), 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_(false), 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.ToEventParametersCallback()); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureWinsockInit(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TCPSocketWin::~TCPSocketWin() { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::Open(AddressFamily family) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(socket_, INVALID_SOCKET); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, 297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) IPPROTO_TCP); 298c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (socket_ == INVALID_SOCKET) { 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PLOG(ERROR) << "CreatePlatformSocket() returned an error"; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SetNonBlocking(socket_)) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = MapSystemError(WSAGetLastError()); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return OK; 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::AdoptConnectedSocket(SOCKET socket, 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const IPEndPoint& peer_address) { 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(CalledOnValidThread()); 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_EQ(socket_, INVALID_SOCKET); 316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!core_); 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) socket_ = socket; 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (SetNonBlocking(socket_)) { 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result = MapSystemError(WSAGetLastError()); 3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_ = new Core(this); 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) peer_address_.reset(new IPEndPoint(peer_address)); 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint TCPSocketWin::AdoptListenSocket(SOCKET socket) { 3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(CalledOnValidThread()); 3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_EQ(socket_, INVALID_SOCKET); 3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu socket_ = socket; 3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (SetNonBlocking(socket_)) { 3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int result = MapSystemError(WSAGetLastError()); 3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Close(); 3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return result; 3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // |core_| is not needed for sockets that are used to accept connections. 3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The operation here is more like Open but with an existing socket. 3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return OK; 3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::Bind(const IPEndPoint& address) { 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(CalledOnValidThread()); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_NE(socket_, INVALID_SOCKET); 35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result = bind(socket_, storage.addr, storage.addr_len); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "bind() returned an error"; 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::Listen(int backlog) { 36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(CalledOnValidThread()); 36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_GT(backlog, 0); 37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_NE(socket_, INVALID_SOCKET); 371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(accept_event_, WSA_INVALID_EVENT); 37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_event_ = WSACreateEvent(); 374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (accept_event_ == WSA_INVALID_EVENT) { 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PLOG(ERROR) << "WSACreateEvent()"; 376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result = listen(socket_, backlog); 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (result < 0) { 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PLOG(ERROR) << "listen() returned an error"; 382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return OK; 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket, 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IPEndPoint* address, 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const CompletionCallback& callback) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket); 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(address); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(accept_callback_.is_null()); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result = AcceptInternal(socket, address); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERR_IO_PENDING) { 40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Start watching. 403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSAEventSelect(socket_, accept_event_, FD_ACCEPT); 404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_watcher_.StartWatching(accept_event_, this); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_ = socket; 40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accept_address_ = address; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_ = callback; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::Connect(const IPEndPoint& address, 415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 416d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(socket_, INVALID_SOCKET); 418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!waiting_connect_); 419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |peer_address_| and |core_| will be non-NULL if Connect() has been called. 421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Unless Close() is called to reset the internal state, a second call to 422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Connect() is not allowed. 423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Please note that we enforce this even if the previous Connect() has 424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // completed and failed. Although it is allowed to connect the same |socket_| 425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // again after a connection attempt failed on Windows, it results in 426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // unspecified behavior according to POSIX. Therefore, we make it behave in 427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the same way as TCPSocketLibevent. 428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!peer_address_ && !core_); 429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) 431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectBegin(AddressList(address)); 432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) peer_address_.reset(new IPEndPoint(address)); 434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = DoConnect(); 436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == ERR_IO_PENDING) { 437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Synchronous operation not supported. 438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!callback.is_null()); 439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_callback_ = callback; 440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_connect_ = true; 441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DoConnectComplete(rv); 443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv; 446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketWin::IsConnected() const { 449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (socket_ == INVALID_SOCKET || waiting_connect_) 452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (waiting_read_) 455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Check if connection is alive. 458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) char c; 459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = recv(socket_, &c, 1, MSG_PEEK); 460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == 0) 461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketWin::IsConnectedAndIdle() const { 469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (socket_ == INVALID_SOCKET || waiting_connect_) 472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (waiting_read_) 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Check if connection is alive and we haven't received any data 478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // unexpectedly. 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) char c; 480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = recv(socket_, &c, 1, MSG_PEEK); 481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv >= 0) 482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (WSAGetLastError() != WSAEWOULDBLOCK) 484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::Read(IOBuffer* buf, 490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int buf_len, 491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(socket_, INVALID_SOCKET); 494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!waiting_read_); 495d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(read_callback_.is_null()); 496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!core_->read_iobuffer_); 497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return DoRead(buf, buf_len, callback); 499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::Write(IOBuffer* buf, 502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int buf_len, 503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(socket_, INVALID_SOCKET); 506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!waiting_write_); 507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(write_callback_.is_null()); 508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_GT(buf_len, 0); 509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!core_->write_iobuffer_); 510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter writes("tcp.writes"); 512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) writes.Increment(); 513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 514d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSABUF write_buffer; 515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_buffer.len = buf_len; 516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_buffer.buf = buf->data(); 517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(wtc): Remove the assertion after enough testing. 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AssertEventNotSignaled(core_->write_overlapped_.hEvent); 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DWORD num; 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = WSASend(socket_, &write_buffer, 1, &num, 0, 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &core_->write_overlapped_, NULL); 523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == 0) { 524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 525d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = static_cast<int>(num); 526d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv > buf_len || rv < 0) { 527d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // It seems that some winsock interceptors report that more was written 528d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // than was available. Treat this as an error. http://crbug.com/27870 529d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len 530d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << " bytes, but " << rv << " bytes reported."; 531d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; 532d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter write_bytes("tcp.write_bytes"); 534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_bytes.Add(rv); 535d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, 536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buf->data()); 537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv; 538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 539d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = WSAGetLastError(); 541d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (os_error != WSA_IO_PENDING) { 542d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int net_error = MapSystemError(os_error); 543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogSocketErrorCallback(net_error, os_error)); 545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return net_error; 546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 547d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 548d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_write_ = true; 549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_callback_ = callback; 550d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->write_iobuffer_ = buf; 551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->write_buffer_length_ = buf_len; 552d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->WatchForWrite(); 553d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_IO_PENDING; 554d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 555d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 556d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const { 557d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 558d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(address); 559d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 560d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SockaddrStorage storage; 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (getsockname(socket_, storage.addr, &storage.addr_len)) 562d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return MapSystemError(WSAGetLastError()); 563d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_ADDRESS_INVALID; 565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::GetPeerAddress(IPEndPoint* address) const { 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(address); 572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!IsConnected()) 573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 574d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *address = *peer_address_; 575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 576d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 57858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::SetDefaultOptionsForServer() { 57958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SetExclusiveAddrUse(); 58058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 58158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::SetDefaultOptionsForClient() { 583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Increase the socket buffer sizes from the default sizes for WinXP. In 584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // performance testing, there is substantial benefit by increasing from 8KB 585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // to 64KB. 586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // See also: 587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // http://support.microsoft.com/kb/823764/EN-US 588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // On Vista, if we manually set these sizes, Vista turns off its receive 589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // window auto-tuning feature. 590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx 591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since Vista's auto-tune is better than any static value we can could set, 592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // only change these on pre-vista machines. 593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_VISTA) { 594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int32 kSocketBufferSize = 64 * 1024; 595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SetSocketReceiveBufferSize(socket_, kSocketBufferSize); 596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SetSocketSendBufferSize(socket_, kSocketBufferSize); 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 599d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DisableNagle(socket_, true); 600d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); 601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 602d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 60358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::SetExclusiveAddrUse() { 6047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // On Windows, a bound end point can be hijacked by another process by 6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE 6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the 6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another 6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // socket to forcibly bind to the end point until the end point is unbound. 6097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. 6107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // MSDN: http://goo.gl/M6fjQ. 6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 6127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Unlike on *nix, on Windows a TCP server socket can always bind to an end 6137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not 6147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // needed here. 6157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 6167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end 6177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // point in TIME_WAIT status. It does not have this effect for a TCP server 6187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // socket. 6197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL true_value = 1; 6217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 6227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch reinterpret_cast<const char*>(&true_value), 6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sizeof(true_value)); 6247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) 6257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return MapSystemError(errno); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 629c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPSocketWin::SetReceiveBufferSize(int32 size) { 630d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return SetSocketReceiveBufferSize(socket_, size); 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 634c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPSocketWin::SetSendBufferSize(int32 size) { 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return SetSocketSendBufferSize(socket_, size); 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { 640d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return SetTCPKeepAlive(socket_, enable, delay); 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketWin::SetNoDelay(bool no_delay) { 644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return DisableNagle(socket_, no_delay); 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TCPSocketWin::Close() { 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 65058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (socket_ != INVALID_SOCKET) { 651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Only log the close event if there's actually a socket to close. 652f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) net_log_.AddEvent(NetLog::EventType::TYPE_SOCKET_CLOSED); 653f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note: don't use CancelIo to cancel pending IO because it doesn't work 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // when there is a Winsock layered service provider. 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // In most socket implementations, closing a socket results in a graceful 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // connection shutdown, but in Winsock we have to call shutdown explicitly. 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // See the MSDN page "Graceful Shutdown, Linger Options, and Socket Closure" 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // at http://msdn.microsoft.com/en-us/library/ms738547.aspx 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) shutdown(socket_, SD_SEND); 662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // This cancels any pending IO. 66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (closesocket(socket_) < 0) 66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PLOG(ERROR) << "closesocket"; 66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) socket_ = INVALID_SOCKET; 66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!accept_callback_.is_null()) { 670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_watcher_.StopWatching(); 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_socket_ = NULL; 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_address_ = NULL; 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_callback_.Reset(); 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (accept_event_) { 677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WSACloseEvent(accept_event_); 678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) accept_event_ = WSA_INVALID_EVENT; 679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (core_) { 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (waiting_connect_) { 683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We closed the socket, so this notification will never come. 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // From MSDN' WSAEventSelect documentation: 685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // "Closing a socket with closesocket also cancels the association and 686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // selection of network events specified in WSAEventSelect for the 687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // socket". 688d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->Release(); 689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->Detach(); 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_ = NULL; 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_connect_ = false; 695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_read_ = false; 696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_write_ = false; 697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_callback_.Reset(); 699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_callback_.Reset(); 700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) peer_address_.reset(); 701d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connect_os_error_ = 0; 702d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 703d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 704d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::StartLoggingMultipleConnectAttempts( 705d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const AddressList& addresses) { 706d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) { 707d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_ = true; 708d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectBegin(addresses); 709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::EndLoggingMultipleConnectAttempts(int net_error) { 715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (logging_multiple_connect_attempts_) { 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectEnd(net_error); 717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_ = false; 718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 72058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 72158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 72258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 72358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket, 72458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IPEndPoint* address) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_socket = accept(socket_, storage.addr, &storage.addr_len); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_socket < 0) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSystemError(WSAGetLastError()); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error != ERR_IO_PENDING) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IPEndPoint ip_end_point; 73558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (closesocket(new_socket) < 0) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "closesocket"; 739effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int net_error = ERR_ADDRESS_INVALID; 740effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 741effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return net_error; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 74358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin( 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.net_log(), net_log_.source())); 745d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int adopt_result = tcp_socket->AdoptConnectedSocket(new_socket, ip_end_point); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adopt_result != OK) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return adopt_result; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 75058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *socket = tcp_socket.Pass(); 75158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *address = ip_end_point; 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, 75358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CreateNetLogIPEndPointCallback(&ip_end_point)); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TCPSocketWin::OnObjectSignaled(HANDLE object) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSANETWORKEVENTS ev; 759d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (WSAEnumNetworkEvents(socket_, accept_event_, &ev) == SOCKET_ERROR) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "WSAEnumNetworkEvents()"; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ev.lNetworkEvents & FD_ACCEPT) { 76558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result = AcceptInternal(accept_socket_, accept_address_); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_ = NULL; 76858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accept_address_ = NULL; 769d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::ResetAndReturn(&accept_callback_).Run(result); 770d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 7724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This happens when a client opens a connection and closes it before we 7734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // have a chance to accept it. 7744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(ev.lNetworkEvents == 0); 7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Start watching the next FD_ACCEPT event. 7774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WSAEventSelect(socket_, accept_event_, FD_ACCEPT); 7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) accept_watcher_.StartWatching(accept_event_, this); 779d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 780d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 781d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 782d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::DoConnect() { 783d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(connect_os_error_, 0); 784d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!core_); 785d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 786d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 787d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogIPEndPointCallback(peer_address_.get())); 788d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 789d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_ = new Core(this); 790d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // WSAEventSelect sets the socket to non-blocking mode as a side effect. 791d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Our connect() and recv() calls require that the socket be non-blocking. 792d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT); 793d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 794d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SockaddrStorage storage; 795d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) 796effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return ERR_ADDRESS_INVALID; 797d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!connect(socket_, storage.addr, storage.addr_len)) { 798d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Connected without waiting! 799d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 800d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The MSDN page for connect says: 801d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // With a nonblocking socket, the connection attempt cannot be completed 802d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // immediately. In this case, connect will return SOCKET_ERROR, and 803d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // WSAGetLastError will return WSAEWOULDBLOCK. 804d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // which implies that for a nonblocking socket, connect never returns 0. 805d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // It's not documented whether the event object will be signaled or not 806d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // if connect does return 0. So the code below is essentially dead code 807d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // and we don't know if it's correct. 808d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 809d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 810d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) 811d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 812d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 813d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = WSAGetLastError(); 814d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (os_error != WSAEWOULDBLOCK) { 815d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "connect failed: " << os_error; 816d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connect_os_error_ = os_error; 817d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = MapConnectError(os_error); 818d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CHECK_NE(ERR_IO_PENDING, rv); 819d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 822d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 823d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->WatchForRead(); 824d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_IO_PENDING; 825d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 826d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 827d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::DoConnectComplete(int result) { 828d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Log the end of this attempt (and any OS error it threw). 829d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = connect_os_error_; 830d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connect_os_error_ = 0; 831d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (result != OK) { 832d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 833d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NetLog::IntegerCallback("os_error", os_error)); 834d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 835d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 836d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 837d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 838d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) 839d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectEnd(result); 840d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 841d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 842d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::LogConnectBegin(const AddressList& addresses) { 843d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter connects("tcp.connect"); 844d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connects.Increment(); 845d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 846d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 847d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) addresses.CreateNetLogCallback()); 848d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 849d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 850d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::LogConnectEnd(int net_error) { 851d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (net_error == OK) 852d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) UpdateConnectionTypeHistograms(CONNECTION_ANY); 853d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 854d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (net_error != OK) { 855d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 856d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 857d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 858d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 859d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) struct sockaddr_storage source_address; 860d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) socklen_t addrlen = sizeof(source_address); 861d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = getsockname( 862d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen); 863d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv != 0) { 864d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "getsockname() [rv: " << rv 865d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "] error: " << WSAGetLastError(); 866d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 867d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 868d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 869d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 870d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 871d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent( 872d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NetLog::TYPE_TCP_CONNECT, 873d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogSourceAddressCallback( 874d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) reinterpret_cast<const struct sockaddr*>(&source_address), 875d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sizeof(source_address))); 876d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 877d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 878d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len, 879d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 880d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!core_->non_blocking_reads_initialized_) { 881d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSAEventSelect(socket_, core_->read_overlapped_.hEvent, 882d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FD_READ | FD_CLOSE); 883d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->non_blocking_reads_initialized_ = true; 884d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 885d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = recv(socket_, buf->data(), buf_len, 0); 886d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == SOCKET_ERROR) { 887d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = WSAGetLastError(); 888d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (os_error != WSAEWOULDBLOCK) { 889d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int net_error = MapSystemError(os_error); 890d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddEvent( 891d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NetLog::TYPE_SOCKET_READ_ERROR, 892d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogSocketErrorCallback(net_error, os_error)); 893d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return net_error; 894d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 895d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 896d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter read_bytes("tcp.read_bytes"); 897d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv > 0) 898d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_bytes.Add(rv); 899d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, 900d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buf->data()); 901d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv; 902d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 903d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 904d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_read_ = true; 905d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_callback_ = callback; 906d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->read_iobuffer_ = buf; 907d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->read_buffer_length_ = buf_len; 908d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->WatchForRead(); 909d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_IO_PENDING; 910d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 911d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 912d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::DidCompleteConnect() { 913d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(waiting_connect_); 914d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!read_callback_.is_null()); 915d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int result; 916d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 917d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSANETWORKEVENTS events; 918d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, 919d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &events); 920d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = 0; 921d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == SOCKET_ERROR) { 922d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 923d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) os_error = WSAGetLastError(); 924d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) result = MapSystemError(os_error); 925d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (events.lNetworkEvents & FD_CONNECT) { 926d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) os_error = events.iErrorCode[FD_CONNECT_BIT]; 927d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) result = MapConnectError(os_error); 928d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 929d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 930d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) result = ERR_UNEXPECTED; 931d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 932d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 933d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connect_os_error_ = os_error; 934d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DoConnectComplete(result); 935d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_connect_ = false; 936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 937d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(result, ERR_IO_PENDING); 938d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::ResetAndReturn(&read_callback_).Run(result); 939d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 941d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::DidCompleteWrite() { 942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(waiting_write_); 943d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!write_callback_.is_null()); 944d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DWORD num_bytes, flags; 946d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 947d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &num_bytes, FALSE, &flags); 948d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSAResetEvent(core_->write_overlapped_.hEvent); 949d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_write_ = false; 950d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv; 951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!ok) { 952d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = WSAGetLastError(); 953d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = MapSystemError(os_error); 954d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 955d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogSocketErrorCallback(rv, os_error)); 956d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 957d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = static_cast<int>(num_bytes); 958d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv > core_->write_buffer_length_ || rv < 0) { 959d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // It seems that some winsock interceptors report that more was written 960d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // than was available. Treat this as an error. http://crbug.com/27870 961d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "Detected broken LSP: Asked to write " 962d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << core_->write_buffer_length_ << " bytes, but " << rv 963d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << " bytes reported."; 964d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; 965d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 966d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter write_bytes("tcp.write_bytes"); 967d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) write_bytes.Add(num_bytes); 968d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes, 969d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->write_iobuffer_->data()); 970d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 971d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 972d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 973d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->write_iobuffer_ = NULL; 974d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 975d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 976d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::ResetAndReturn(&write_callback_).Run(rv); 977d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 978d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 979d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketWin::DidSignalRead() { 980d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(waiting_read_); 981d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!read_callback_.is_null()); 982d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 983d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int os_error = 0; 984d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WSANETWORKEVENTS network_events; 985d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, 986d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &network_events); 987d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == SOCKET_ERROR) { 988d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) os_error = WSAGetLastError(); 989d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = MapSystemError(os_error); 990d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (network_events.lNetworkEvents) { 991d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0); 992d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If network_events.lNetworkEvents is FD_CLOSE and 993d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful 994d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // connection closure. It is tempting to directly set rv to 0 in 995d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // this case, but the MSDN pages for WSAEventSelect and 996d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // WSAAsyncSelect recommend we still call DoRead(): 997d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // FD_CLOSE should only be posted after all data is read from a 998d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // socket, but an application should check for remaining data upon 999d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // receipt of FD_CLOSE to avoid any possibility of losing data. 1000d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 1001d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If network_events.iErrorCode[FD_READ_BIT] or 1002d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call 1003d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // DoRead() because recv() reports a more accurate error code 1004d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was 1005d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // reset. 1006d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_, 1007d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) read_callback_); 1008d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rv == ERR_IO_PENDING) 1009d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 1010d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 1011d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // This may happen because Read() may succeed synchronously and 1012d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // consume all the received data without resetting the event object. 1013d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->WatchForRead(); 1014d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 1015d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1016d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1017d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) waiting_read_ = false; 1018d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->read_iobuffer_ = NULL; 1019d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) core_->read_buffer_length_ = 0; 1020d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1021d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 1022d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::ResetAndReturn(&read_callback_).Run(rv); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1026