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