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