OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/socket/tcp_socket_win.h" | 5 #include "net/socket/tcp_socket_win.h" |
6 | 6 |
7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
8 | 8 |
9 #include "base/callback_helpers.h" | |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/stats_counters.h" | |
12 #include "base/win/windows_version.h" | |
13 #include "net/base/address_list.h" | |
14 #include "net/base/connection_type_histograms.h" | |
15 #include "net/base/io_buffer.h" | |
10 #include "net/base/ip_endpoint.h" | 16 #include "net/base/ip_endpoint.h" |
11 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
12 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
19 #include "net/base/network_change_notifier.h" | |
13 #include "net/base/winsock_init.h" | 20 #include "net/base/winsock_init.h" |
14 #include "net/base/winsock_util.h" | 21 #include "net/base/winsock_util.h" |
15 #include "net/socket/socket_descriptor.h" | 22 #include "net/socket/socket_descriptor.h" |
16 #include "net/socket/socket_net_log_params.h" | 23 #include "net/socket/socket_net_log_params.h" |
17 | 24 |
18 namespace net { | 25 namespace net { |
19 | 26 |
27 namespace { | |
28 | |
29 const int kTCPKeepAliveSeconds = 45; | |
30 | |
31 bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) { | |
32 int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, | |
33 reinterpret_cast<const char*>(&size), sizeof(size)); | |
34 DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError(); | |
35 return rv == 0; | |
36 } | |
37 | |
38 bool SetSocketSendBufferSize(SOCKET socket, int32 size) { | |
39 int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, | |
40 reinterpret_cast<const char*>(&size), sizeof(size)); | |
41 DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError(); | |
42 return rv == 0; | |
43 } | |
44 | |
45 // Disable Nagle. | |
46 // The Nagle implementation on windows is governed by RFC 896. The idea | |
47 // behind Nagle is to reduce small packets on the network. When Nagle is | |
48 // enabled, if a partial packet has been sent, the TCP stack will disallow | |
49 // further *partial* packets until an ACK has been received from the other | |
50 // side. Good applications should always strive to send as much data as | |
51 // possible and avoid partial-packet sends. However, in most real world | |
52 // applications, there are edge cases where this does not happen, and two | |
53 // partial packets may be sent back to back. For a browser, it is NEVER | |
54 // a benefit to delay for an RTT before the second packet is sent. | |
55 // | |
56 // As a practical example in Chromium today, consider the case of a small | |
57 // POST. I have verified this: | |
58 // Client writes 649 bytes of header (partial packet #1) | |
59 // Client writes 50 bytes of POST data (partial packet #2) | |
60 // In the above example, with Nagle, a RTT delay is inserted between these | |
61 // two sends due to nagle. RTTs can easily be 100ms or more. The best | |
62 // fix is to make sure that for POSTing data, we write as much data as | |
63 // possible and minimize partial packets. We will fix that. But disabling | |
64 // Nagle also ensure we don't run into this delay in other edge cases. | |
65 // See also: | |
66 // http://technet.microsoft.com/en-us/library/bb726981.aspx | |
67 bool DisableNagle(SOCKET socket, bool disable) { | |
68 BOOL val = disable ? TRUE : FALSE; | |
69 int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, | |
70 reinterpret_cast<const char*>(&val), | |
71 sizeof(val)); | |
72 DCHECK(!rv) << "Could not disable nagle"; | |
73 return rv == 0; | |
74 } | |
75 | |
76 // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP | |
77 // connections. See http://crbug.com/27400 for details. | |
78 bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { | |
79 int delay = delay_secs * 1000; | |
80 struct tcp_keepalive keepalive_vals = { | |
81 enable ? 1 : 0, // TCP keep-alive on. | |
82 delay, // Delay seconds before sending first TCP keep-alive packet. | |
83 delay, // Delay seconds between sending TCP keep-alive packets. | |
84 }; | |
85 DWORD bytes_returned = 0xABAB; | |
86 int rv = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &keepalive_vals, | |
87 sizeof(keepalive_vals), NULL, 0, | |
88 &bytes_returned, NULL, NULL); | |
89 DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket | |
90 << " [error: " << WSAGetLastError() << "]."; | |
91 | |
92 // Disregard any failure in disabling nagle or enabling TCP Keep-Alive. | |
93 return rv == 0; | |
94 } | |
95 | |
96 int MapConnectError(int os_error) { | |
97 switch (os_error) { | |
98 // connect fails with WSAEACCES when Windows Firewall blocks the | |
99 // connection. | |
100 case WSAEACCES: | |
101 return ERR_NETWORK_ACCESS_DENIED; | |
102 case WSAETIMEDOUT: | |
103 return ERR_CONNECTION_TIMED_OUT; | |
104 default: { | |
105 int net_error = MapSystemError(os_error); | |
106 if (net_error == ERR_FAILED) | |
107 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. | |
108 | |
109 // Give a more specific error when the user is offline. | |
110 if (net_error == ERR_ADDRESS_UNREACHABLE && | |
111 NetworkChangeNotifier::IsOffline()) { | |
112 return ERR_INTERNET_DISCONNECTED; | |
113 } | |
114 | |
115 return net_error; | |
116 } | |
117 } | |
118 } | |
119 | |
120 } // namespace | |
121 | |
122 //----------------------------------------------------------------------------- | |
123 | |
124 // This class encapsulates all the state that has to be preserved as long as | |
125 // there is a network IO operation in progress. If the owner TCPSocketWin is | |
126 // destroyed while an operation is in progress, the Core is detached and it | |
127 // lives until the operation completes and the OS doesn't reference any resource | |
128 // declared on this class anymore. | |
129 class TCPSocketWin::Core : public base::RefCounted<Core> { | |
130 public: | |
131 explicit Core(TCPSocketWin* socket); | |
132 | |
133 // Start watching for the end of a read or write operation. | |
134 void WatchForRead(); | |
135 void WatchForWrite(); | |
136 | |
137 // The TCPSocketWin is going away. | |
138 void Detach() { socket_ = NULL; } | |
139 | |
140 // The separate OVERLAPPED variables for asynchronous operation. | |
141 // |read_overlapped_| is used for both Connect() and Read(). | |
142 // |write_overlapped_| is only used for Write(); | |
143 OVERLAPPED read_overlapped_; | |
144 OVERLAPPED write_overlapped_; | |
145 | |
146 // The buffers used in Read() and Write(). | |
147 scoped_refptr<IOBuffer> read_iobuffer_; | |
148 scoped_refptr<IOBuffer> write_iobuffer_; | |
149 int read_buffer_length_; | |
150 int write_buffer_length_; | |
151 | |
152 bool non_blocking_reads_initialized_; | |
153 | |
154 private: | |
155 friend class base::RefCounted<Core>; | |
156 | |
157 class ReadDelegate : public base::win::ObjectWatcher::Delegate { | |
158 public: | |
159 explicit ReadDelegate(Core* core) : core_(core) {} | |
160 virtual ~ReadDelegate() {} | |
161 | |
162 // base::ObjectWatcher::Delegate methods: | |
163 virtual void OnObjectSignaled(HANDLE object); | |
164 | |
165 private: | |
166 Core* const core_; | |
167 }; | |
168 | |
169 class WriteDelegate : public base::win::ObjectWatcher::Delegate { | |
170 public: | |
171 explicit WriteDelegate(Core* core) : core_(core) {} | |
172 virtual ~WriteDelegate() {} | |
173 | |
174 // base::ObjectWatcher::Delegate methods: | |
175 virtual void OnObjectSignaled(HANDLE object); | |
176 | |
177 private: | |
178 Core* const core_; | |
179 }; | |
180 | |
181 ~Core(); | |
182 | |
183 // The socket that created this object. | |
184 TCPSocketWin* socket_; | |
185 | |
186 // |reader_| handles the signals from |read_watcher_|. | |
187 ReadDelegate reader_; | |
188 // |writer_| handles the signals from |write_watcher_|. | |
189 WriteDelegate writer_; | |
190 | |
191 // |read_watcher_| watches for events from Connect() and Read(). | |
192 base::win::ObjectWatcher read_watcher_; | |
193 // |write_watcher_| watches for events from Write(); | |
194 base::win::ObjectWatcher write_watcher_; | |
195 | |
196 DISALLOW_COPY_AND_ASSIGN(Core); | |
197 }; | |
198 | |
199 TCPSocketWin::Core::Core(TCPSocketWin* socket) | |
200 : read_buffer_length_(0), | |
201 write_buffer_length_(0), | |
202 non_blocking_reads_initialized_(false), | |
203 socket_(socket), | |
204 reader_(this), | |
205 writer_(this) { | |
206 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | |
207 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | |
208 | |
209 read_overlapped_.hEvent = WSACreateEvent(); | |
210 write_overlapped_.hEvent = WSACreateEvent(); | |
211 } | |
212 | |
213 TCPSocketWin::Core::~Core() { | |
214 // Make sure the message loop is not watching this object anymore. | |
215 read_watcher_.StopWatching(); | |
216 write_watcher_.StopWatching(); | |
217 | |
218 WSACloseEvent(read_overlapped_.hEvent); | |
219 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); | |
220 WSACloseEvent(write_overlapped_.hEvent); | |
221 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); | |
222 } | |
223 | |
224 void TCPSocketWin::Core::WatchForRead() { | |
225 // We grab an extra reference because there is an IO operation in progress. | |
226 // Balanced in ReadDelegate::OnObjectSignaled(). | |
227 AddRef(); | |
228 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); | |
229 } | |
230 | |
231 void TCPSocketWin::Core::WatchForWrite() { | |
232 // We grab an extra reference because there is an IO operation in progress. | |
233 // Balanced in WriteDelegate::OnObjectSignaled(). | |
234 AddRef(); | |
235 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); | |
236 } | |
237 | |
238 void TCPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { | |
239 DCHECK_EQ(object, core_->read_overlapped_.hEvent); | |
240 if (core_->socket_) { | |
241 if (core_->socket_->waiting_connect_) | |
242 core_->socket_->DidCompleteConnect(); | |
243 else | |
244 core_->socket_->DidSignalRead(); | |
245 } | |
246 | |
247 core_->Release(); | |
248 } | |
249 | |
250 void TCPSocketWin::Core::WriteDelegate::OnObjectSignaled( | |
251 HANDLE object) { | |
252 DCHECK_EQ(object, core_->write_overlapped_.hEvent); | |
253 if (core_->socket_) | |
254 core_->socket_->DidCompleteWrite(); | |
255 | |
256 core_->Release(); | |
257 } | |
258 | |
259 //----------------------------------------------------------------------------- | |
260 | |
20 TCPSocketWin::TCPSocketWin(net::NetLog* net_log, | 261 TCPSocketWin::TCPSocketWin(net::NetLog* net_log, |
21 const net::NetLog::Source& source) | 262 const net::NetLog::Source& source) |
22 : socket_(INVALID_SOCKET), | 263 : socket_(INVALID_SOCKET), |
23 socket_event_(WSA_INVALID_EVENT), | 264 accept_event_(WSA_INVALID_EVENT), |
24 accept_socket_(NULL), | 265 accept_socket_(NULL), |
25 accept_address_(NULL), | 266 accept_address_(NULL), |
267 waiting_connect_(false), | |
268 waiting_read_(false), | |
269 waiting_write_(false), | |
270 connect_os_error_(0), | |
271 logging_multiple_connect_attempts_(false), | |
26 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 272 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
27 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 273 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
28 source.ToEventParametersCallback()); | 274 source.ToEventParametersCallback()); |
29 EnsureWinsockInit(); | 275 EnsureWinsockInit(); |
30 } | 276 } |
31 | 277 |
32 TCPSocketWin::~TCPSocketWin() { | 278 TCPSocketWin::~TCPSocketWin() { |
33 Close(); | 279 Close(); |
34 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 280 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
35 } | 281 } |
36 | 282 |
37 int TCPSocketWin::Create(AddressFamily family) { | 283 int TCPSocketWin::Open(AddressFamily family) { |
38 DCHECK(CalledOnValidThread()); | 284 DCHECK(CalledOnValidThread()); |
39 DCHECK_EQ(socket_, INVALID_SOCKET); | 285 DCHECK_EQ(socket_, INVALID_SOCKET); |
40 | 286 |
41 socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, | 287 socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, |
42 IPPROTO_TCP); | 288 IPPROTO_TCP); |
43 if (socket_ == INVALID_SOCKET) { | 289 if (socket_ == INVALID_SOCKET) { |
44 PLOG(ERROR) << "CreatePlatformSocket() returned an error"; | 290 PLOG(ERROR) << "CreatePlatformSocket() returned an error"; |
45 return MapSystemError(WSAGetLastError()); | 291 return MapSystemError(WSAGetLastError()); |
46 } | 292 } |
47 | 293 |
48 if (SetNonBlocking(socket_)) { | 294 if (SetNonBlocking(socket_)) { |
49 int result = MapSystemError(WSAGetLastError()); | 295 int result = MapSystemError(WSAGetLastError()); |
50 Close(); | 296 Close(); |
51 return result; | 297 return result; |
52 } | 298 } |
53 | 299 |
54 return OK; | 300 return OK; |
55 } | 301 } |
56 | 302 |
57 int TCPSocketWin::Adopt(SOCKET socket) { | 303 int TCPSocketWin::AdoptConnectedSocket(SOCKET socket, |
304 const IPEndPoint& peer_address) { | |
58 DCHECK(CalledOnValidThread()); | 305 DCHECK(CalledOnValidThread()); |
59 DCHECK_EQ(socket_, INVALID_SOCKET); | 306 DCHECK_EQ(socket_, INVALID_SOCKET); |
307 DCHECK(!core_); | |
60 | 308 |
61 socket_ = socket; | 309 socket_ = socket; |
62 | 310 |
63 if (SetNonBlocking(socket_)) { | 311 if (SetNonBlocking(socket_)) { |
64 int result = MapSystemError(WSAGetLastError()); | 312 int result = MapSystemError(WSAGetLastError()); |
65 Close(); | 313 Close(); |
66 return result; | 314 return result; |
67 } | 315 } |
68 | 316 |
317 core_ = new Core(this); | |
318 peer_address_.reset(new IPEndPoint(peer_address)); | |
319 | |
69 return OK; | 320 return OK; |
70 } | 321 } |
71 | 322 |
72 SOCKET TCPSocketWin::Release() { | |
73 DCHECK(CalledOnValidThread()); | |
74 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); | |
75 DCHECK(accept_callback_.is_null()); | |
76 | |
77 SOCKET result = socket_; | |
78 socket_ = INVALID_SOCKET; | |
79 return result; | |
80 } | |
81 | |
82 int TCPSocketWin::Bind(const IPEndPoint& address) { | 323 int TCPSocketWin::Bind(const IPEndPoint& address) { |
83 DCHECK(CalledOnValidThread()); | 324 DCHECK(CalledOnValidThread()); |
84 DCHECK_NE(socket_, INVALID_SOCKET); | 325 DCHECK_NE(socket_, INVALID_SOCKET); |
85 | 326 |
86 SockaddrStorage storage; | 327 SockaddrStorage storage; |
87 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 328 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
88 return ERR_ADDRESS_INVALID; | 329 return ERR_ADDRESS_INVALID; |
89 | 330 |
90 int result = bind(socket_, storage.addr, storage.addr_len); | 331 int result = bind(socket_, storage.addr, storage.addr_len); |
91 if (result < 0) { | 332 if (result < 0) { |
92 PLOG(ERROR) << "bind() returned an error"; | 333 PLOG(ERROR) << "bind() returned an error"; |
93 return MapSystemError(WSAGetLastError()); | 334 return MapSystemError(WSAGetLastError()); |
94 } | 335 } |
95 | 336 |
96 return OK; | 337 return OK; |
97 } | 338 } |
98 | 339 |
99 int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const { | |
100 DCHECK(CalledOnValidThread()); | |
101 DCHECK(address); | |
102 | |
103 SockaddrStorage storage; | |
104 if (getsockname(socket_, storage.addr, &storage.addr_len)) | |
105 return MapSystemError(WSAGetLastError()); | |
106 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | |
107 return ERR_FAILED; | |
108 | |
109 return OK; | |
110 } | |
111 | |
112 int TCPSocketWin::Listen(int backlog) { | 340 int TCPSocketWin::Listen(int backlog) { |
113 DCHECK(CalledOnValidThread()); | 341 DCHECK(CalledOnValidThread()); |
114 DCHECK_GT(backlog, 0); | 342 DCHECK_GT(backlog, 0); |
115 DCHECK_NE(socket_, INVALID_SOCKET); | 343 DCHECK_NE(socket_, INVALID_SOCKET); |
116 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); | 344 DCHECK_EQ(accept_event_, WSA_INVALID_EVENT); |
117 | 345 |
118 socket_event_ = WSACreateEvent(); | 346 accept_event_ = WSACreateEvent(); |
119 if (socket_event_ == WSA_INVALID_EVENT) { | 347 if (accept_event_ == WSA_INVALID_EVENT) { |
120 PLOG(ERROR) << "WSACreateEvent()"; | 348 PLOG(ERROR) << "WSACreateEvent()"; |
121 return ERR_FAILED; | 349 return MapSystemError(WSAGetLastError()); |
122 } | 350 } |
123 | 351 |
124 int result = listen(socket_, backlog); | 352 int result = listen(socket_, backlog); |
125 if (result < 0) { | 353 if (result < 0) { |
126 PLOG(ERROR) << "listen() returned an error"; | 354 PLOG(ERROR) << "listen() returned an error"; |
127 result = MapSystemError(WSAGetLastError()); | 355 return MapSystemError(WSAGetLastError()); |
128 return result; | |
129 } | 356 } |
130 | 357 |
131 return OK; | 358 return OK; |
132 } | 359 } |
133 | 360 |
134 int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket, | 361 int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket, |
135 IPEndPoint* address, | 362 IPEndPoint* address, |
136 const CompletionCallback& callback) { | 363 const CompletionCallback& callback) { |
137 DCHECK(CalledOnValidThread()); | 364 DCHECK(CalledOnValidThread()); |
138 DCHECK(socket); | 365 DCHECK(socket); |
139 DCHECK(address); | 366 DCHECK(address); |
140 DCHECK(!callback.is_null()); | 367 DCHECK(!callback.is_null()); |
141 DCHECK(accept_callback_.is_null()); | 368 DCHECK(accept_callback_.is_null()); |
142 | 369 |
143 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); | 370 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); |
144 | 371 |
145 int result = AcceptInternal(socket, address); | 372 int result = AcceptInternal(socket, address); |
146 | 373 |
147 if (result == ERR_IO_PENDING) { | 374 if (result == ERR_IO_PENDING) { |
148 // Start watching. | 375 // Start watching. |
149 WSAEventSelect(socket_, socket_event_, FD_ACCEPT); | 376 WSAEventSelect(socket_, accept_event_, FD_ACCEPT); |
150 accept_watcher_.StartWatching(socket_event_, this); | 377 accept_watcher_.StartWatching(accept_event_, this); |
151 | 378 |
152 accept_socket_ = socket; | 379 accept_socket_ = socket; |
153 accept_address_ = address; | 380 accept_address_ = address; |
154 accept_callback_ = callback; | 381 accept_callback_ = callback; |
155 } | 382 } |
156 | 383 |
157 return result; | 384 return result; |
158 } | 385 } |
159 | 386 |
387 int TCPSocketWin::Connect(const IPEndPoint& address, | |
388 const CompletionCallback& callback) { | |
389 DCHECK(CalledOnValidThread()); | |
390 DCHECK_NE(socket_, INVALID_SOCKET); | |
391 DCHECK(!waiting_connect_); | |
392 | |
393 // |peer_address_| and |core_| will be non-NULL if Connect() has been called. | |
394 // Unless Close() is called to reset the internal state, a second call to | |
395 // Connect() is not allowed. | |
396 // Please note that we enforce this even if the previous Connect() has | |
397 // completed and failed. Although it is allowed to connect the same |socket_| | |
398 // again after a connection attempt failed on Windows, it results in | |
399 // unspecified behavior according to POSIX. Therefore, we make it behave in | |
400 // the same way as TCPSocketLibevent. | |
401 DCHECK(!peer_address_ && !core_); | |
402 | |
403 if (!logging_multiple_connect_attempts_) | |
404 LogConnectBegin(AddressList(address)); | |
405 | |
406 peer_address_.reset(new IPEndPoint(address)); | |
407 | |
408 int rv = DoConnect(); | |
409 if (rv == ERR_IO_PENDING) { | |
410 // Synchronous operation not supported. | |
411 DCHECK(!callback.is_null()); | |
412 read_callback_ = callback; | |
413 waiting_connect_ = true; | |
414 } else { | |
415 DoConnectComplete(rv); | |
416 } | |
417 | |
418 return rv; | |
419 } | |
420 | |
421 bool TCPSocketWin::IsConnected() const { | |
422 DCHECK(CalledOnValidThread()); | |
423 | |
424 if (socket_ == INVALID_SOCKET || waiting_connect_) | |
425 return false; | |
426 | |
427 if (waiting_read_) | |
428 return true; | |
429 | |
430 // Check if connection is alive. | |
431 char c; | |
432 int rv = recv(socket_, &c, 1, MSG_PEEK); | |
433 if (rv == 0) | |
434 return false; | |
435 if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) | |
436 return false; | |
437 | |
438 return true; | |
439 } | |
440 | |
441 bool TCPSocketWin::IsConnectedAndIdle() const { | |
442 DCHECK(CalledOnValidThread()); | |
443 | |
444 if (socket_ == INVALID_SOCKET || waiting_connect_) | |
445 return false; | |
446 | |
447 if (waiting_read_) | |
448 return true; | |
449 | |
450 // Check if connection is alive and we haven't received any data | |
451 // unexpectedly. | |
452 char c; | |
453 int rv = recv(socket_, &c, 1, MSG_PEEK); | |
454 if (rv >= 0) | |
455 return false; | |
456 if (WSAGetLastError() != WSAEWOULDBLOCK) | |
457 return false; | |
458 | |
459 return true; | |
460 } | |
461 | |
462 int TCPSocketWin::Read(IOBuffer* buf, | |
463 int buf_len, | |
464 const CompletionCallback& callback) { | |
465 DCHECK(CalledOnValidThread()); | |
466 DCHECK_NE(socket_, INVALID_SOCKET); | |
467 DCHECK(!waiting_read_); | |
468 DCHECK(read_callback_.is_null()); | |
469 DCHECK(!core_->read_iobuffer_); | |
470 | |
471 return DoRead(buf, buf_len, callback); | |
472 } | |
473 | |
474 int TCPSocketWin::Write(IOBuffer* buf, | |
475 int buf_len, | |
476 const CompletionCallback& callback) { | |
477 DCHECK(CalledOnValidThread()); | |
478 DCHECK_NE(socket_, INVALID_SOCKET); | |
479 DCHECK(!waiting_write_); | |
480 DCHECK(write_callback_.is_null()); | |
481 DCHECK_GT(buf_len, 0); | |
482 DCHECK(!core_->write_iobuffer_); | |
483 | |
484 base::StatsCounter writes("tcp.writes"); | |
485 writes.Increment(); | |
486 | |
487 WSABUF write_buffer; | |
488 write_buffer.len = buf_len; | |
489 write_buffer.buf = buf->data(); | |
490 | |
491 // TODO(wtc): Remove the assertion after enough testing. | |
492 AssertEventNotSignaled(core_->write_overlapped_.hEvent); | |
493 DWORD num; | |
494 int rv = WSASend(socket_, &write_buffer, 1, &num, 0, | |
495 &core_->write_overlapped_, NULL); | |
496 if (rv == 0) { | |
497 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { | |
498 rv = static_cast<int>(num); | |
499 if (rv > buf_len || rv < 0) { | |
500 // It seems that some winsock interceptors report that more was written | |
501 // than was available. Treat this as an error. http://crbug.com/27870 | |
502 LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len | |
503 << " bytes, but " << rv << " bytes reported."; | |
504 return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; | |
505 } | |
506 base::StatsCounter write_bytes("tcp.write_bytes"); | |
507 write_bytes.Add(rv); | |
508 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, | |
509 buf->data()); | |
510 return rv; | |
511 } | |
512 } else { | |
513 int os_error = WSAGetLastError(); | |
514 if (os_error != WSA_IO_PENDING) { | |
515 int net_error = MapSystemError(os_error); | |
516 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, | |
517 CreateNetLogSocketErrorCallback(net_error, os_error)); | |
518 return net_error; | |
519 } | |
520 } | |
521 waiting_write_ = true; | |
522 write_callback_ = callback; | |
523 core_->write_iobuffer_ = buf; | |
524 core_->write_buffer_length_ = buf_len; | |
525 core_->WatchForWrite(); | |
526 return ERR_IO_PENDING; | |
527 } | |
528 | |
529 int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const { | |
530 DCHECK(CalledOnValidThread()); | |
531 DCHECK(address); | |
532 | |
533 SockaddrStorage storage; | |
534 if (getsockname(socket_, storage.addr, &storage.addr_len)) | |
535 return MapSystemError(WSAGetLastError()); | |
536 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | |
537 return ERR_ADDRESS_INVALID; | |
538 | |
539 return OK; | |
540 } | |
541 | |
542 int TCPSocketWin::GetPeerAddress(IPEndPoint* address) const { | |
543 DCHECK(CalledOnValidThread()); | |
544 DCHECK(address); | |
545 if (!IsConnected()) | |
546 return ERR_SOCKET_NOT_CONNECTED; | |
547 *address = *peer_address_; | |
548 return OK; | |
549 } | |
550 | |
160 int TCPSocketWin::SetDefaultOptionsForServer() { | 551 int TCPSocketWin::SetDefaultOptionsForServer() { |
161 return SetExclusiveAddrUse(); | 552 return SetExclusiveAddrUse(); |
162 } | 553 } |
163 | 554 |
555 void TCPSocketWin::SetDefaultOptionsForClient() { | |
556 // Increase the socket buffer sizes from the default sizes for WinXP. In | |
557 // performance testing, there is substantial benefit by increasing from 8KB | |
558 // to 64KB. | |
559 // See also: | |
560 // http://support.microsoft.com/kb/823764/EN-US | |
561 // On Vista, if we manually set these sizes, Vista turns off its receive | |
562 // window auto-tuning feature. | |
563 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx | |
564 // Since Vista's auto-tune is better than any static value we can could set, | |
565 // only change these on pre-vista machines. | |
566 if (base::win::GetVersion() < base::win::VERSION_VISTA) { | |
567 const int32 kSocketBufferSize = 64 * 1024; | |
568 SetSocketReceiveBufferSize(socket_, kSocketBufferSize); | |
569 SetSocketSendBufferSize(socket_, kSocketBufferSize); | |
570 } | |
571 | |
572 DisableNagle(socket_, true); | |
573 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); | |
574 } | |
575 | |
164 int TCPSocketWin::SetExclusiveAddrUse() { | 576 int TCPSocketWin::SetExclusiveAddrUse() { |
165 // On Windows, a bound end point can be hijacked by another process by | 577 // On Windows, a bound end point can be hijacked by another process by |
166 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE | 578 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE |
167 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the | 579 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the |
168 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another | 580 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another |
169 // socket to forcibly bind to the end point until the end point is unbound. | 581 // socket to forcibly bind to the end point until the end point is unbound. |
170 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. | 582 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. |
171 // MSDN: http://goo.gl/M6fjQ. | 583 // MSDN: http://goo.gl/M6fjQ. |
172 // | 584 // |
173 // Unlike on *nix, on Windows a TCP server socket can always bind to an end | 585 // Unlike on *nix, on Windows a TCP server socket can always bind to an end |
174 // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not | 586 // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not |
175 // needed here. | 587 // needed here. |
176 // | 588 // |
177 // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end | 589 // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end |
178 // point in TIME_WAIT status. It does not have this effect for a TCP server | 590 // point in TIME_WAIT status. It does not have this effect for a TCP server |
179 // socket. | 591 // socket. |
180 | 592 |
181 BOOL true_value = 1; | 593 BOOL true_value = 1; |
182 int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, | 594 int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, |
183 reinterpret_cast<const char*>(&true_value), | 595 reinterpret_cast<const char*>(&true_value), |
184 sizeof(true_value)); | 596 sizeof(true_value)); |
185 if (rv < 0) | 597 if (rv < 0) |
186 return MapSystemError(errno); | 598 return MapSystemError(errno); |
187 return OK; | 599 return OK; |
188 } | 600 } |
189 | 601 |
602 bool TCPSocketWin::SetReceiveBufferSize(int32 size) { | |
603 DCHECK(CalledOnValidThread()); | |
604 return SetSocketReceiveBufferSize(socket_, size); | |
605 } | |
606 | |
607 bool TCPSocketWin::SetSendBufferSize(int32 size) { | |
608 DCHECK(CalledOnValidThread()); | |
609 return SetSocketSendBufferSize(socket_, size); | |
610 } | |
611 | |
612 bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { | |
613 return SetTCPKeepAlive(socket_, enable, delay); | |
614 } | |
615 | |
616 bool TCPSocketWin::SetNoDelay(bool no_delay) { | |
617 return DisableNagle(socket_, no_delay); | |
618 } | |
619 | |
190 void TCPSocketWin::Close() { | 620 void TCPSocketWin::Close() { |
wtc
2013/09/13 16:33:05
The property I want from Close() is that members t
yzshen1
2013/09/13 18:16:44
I tried to make it simple: Close() is always safe
| |
621 DCHECK(CalledOnValidThread()); | |
622 | |
191 if (socket_ != INVALID_SOCKET) { | 623 if (socket_ != INVALID_SOCKET) { |
624 // Note: don't use CancelIo to cancel pending IO because it doesn't work | |
625 // when there is a Winsock layered service provider. | |
626 | |
627 // In most socket implementations, closing a socket results in a graceful | |
628 // connection shutdown, but in Winsock we have to call shutdown explicitly. | |
629 // See the MSDN page "Graceful Shutdown, Linger Options, and Socket Closure" | |
630 // at http://msdn.microsoft.com/en-us/library/ms738547.aspx | |
631 shutdown(socket_, SD_SEND); | |
632 | |
633 // This cancels any pending IO. | |
192 if (closesocket(socket_) < 0) | 634 if (closesocket(socket_) < 0) |
193 PLOG(ERROR) << "closesocket"; | 635 PLOG(ERROR) << "closesocket"; |
194 socket_ = INVALID_SOCKET; | 636 socket_ = INVALID_SOCKET; |
195 } | 637 } |
196 | 638 |
197 if (socket_event_) { | 639 if (accept_event_) { |
198 WSACloseEvent(socket_event_); | 640 WSACloseEvent(accept_event_); |
199 socket_event_ = WSA_INVALID_EVENT; | 641 accept_event_ = WSA_INVALID_EVENT; |
642 } | |
643 | |
644 if (!accept_callback_.is_null()) { | |
645 accept_watcher_.StopWatching(); | |
646 accept_socket_ = NULL; | |
647 accept_address_ = NULL; | |
648 accept_callback_.Reset(); | |
649 } | |
650 | |
651 if (core_) { | |
652 if (waiting_connect_) { | |
653 // We closed the socket, so this notification will never come. | |
654 // From MSDN' WSAEventSelect documentation: | |
655 // "Closing a socket with closesocket also cancels the association and | |
656 // selection of network events specified in WSAEventSelect for the | |
657 // socket". | |
658 core_->Release(); | |
659 } | |
660 core_->Detach(); | |
661 core_ = NULL; | |
662 } | |
663 | |
664 waiting_connect_ = false; | |
665 waiting_read_ = false; | |
666 waiting_write_ = false; | |
667 | |
668 read_callback_.Reset(); | |
669 write_callback_.Reset(); | |
670 peer_address_.reset(); | |
671 connect_os_error_ = 0; | |
672 } | |
673 | |
674 bool TCPSocketWin::UsingTCPFastOpen() const { | |
675 // Not supported on windows. | |
676 return false; | |
677 } | |
678 | |
679 void TCPSocketWin::StartLoggingMultipleConnectAttempts( | |
680 const AddressList& addresses) { | |
681 if (!logging_multiple_connect_attempts_) { | |
682 logging_multiple_connect_attempts_ = true; | |
683 LogConnectBegin(addresses); | |
684 } else { | |
685 NOTREACHED(); | |
200 } | 686 } |
201 } | 687 } |
202 | 688 |
689 void TCPSocketWin::EndLoggingMultipleConnectAttempts(int net_error) { | |
690 if (logging_multiple_connect_attempts_) { | |
691 LogConnectEnd(net_error); | |
692 logging_multiple_connect_attempts_ = false; | |
693 } else { | |
694 NOTREACHED(); | |
695 } | |
696 } | |
697 | |
203 int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket, | 698 int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket, |
204 IPEndPoint* address) { | 699 IPEndPoint* address) { |
205 SockaddrStorage storage; | 700 SockaddrStorage storage; |
206 int new_socket = accept(socket_, storage.addr, &storage.addr_len); | 701 int new_socket = accept(socket_, storage.addr, &storage.addr_len); |
wtc
2013/09/13 16:33:05
This shows our listening sockets are calling accep
yzshen1
2013/09/13 18:16:44
Ah, I didn't realize that. Thanks for telling me.
| |
207 if (new_socket < 0) { | 702 if (new_socket < 0) { |
208 int net_error = MapSystemError(WSAGetLastError()); | 703 int net_error = MapSystemError(WSAGetLastError()); |
209 if (net_error != ERR_IO_PENDING) | 704 if (net_error != ERR_IO_PENDING) |
210 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); | 705 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); |
211 return net_error; | 706 return net_error; |
212 } | 707 } |
213 | 708 |
214 IPEndPoint ip_end_point; | 709 IPEndPoint ip_end_point; |
215 if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { | 710 if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { |
216 NOTREACHED(); | 711 NOTREACHED(); |
217 if (closesocket(new_socket) < 0) | 712 if (closesocket(new_socket) < 0) |
218 PLOG(ERROR) << "closesocket"; | 713 PLOG(ERROR) << "closesocket"; |
219 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); | 714 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); |
220 return ERR_FAILED; | 715 return ERR_FAILED; |
221 } | 716 } |
222 scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin( | 717 scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin( |
223 net_log_.net_log(), net_log_.source())); | 718 net_log_.net_log(), net_log_.source())); |
224 int adopt_result = tcp_socket->Adopt(new_socket); | 719 int adopt_result = tcp_socket->AdoptConnectedSocket(new_socket, ip_end_point); |
225 if (adopt_result != OK) { | 720 if (adopt_result != OK) { |
226 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); | 721 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); |
227 return adopt_result; | 722 return adopt_result; |
228 } | 723 } |
229 *socket = tcp_socket.Pass(); | 724 *socket = tcp_socket.Pass(); |
230 *address = ip_end_point; | 725 *address = ip_end_point; |
231 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, | 726 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, |
232 CreateNetLogIPEndPointCallback(&ip_end_point)); | 727 CreateNetLogIPEndPointCallback(&ip_end_point)); |
233 return OK; | 728 return OK; |
234 } | 729 } |
235 | 730 |
236 void TCPSocketWin::OnObjectSignaled(HANDLE object) { | 731 void TCPSocketWin::OnObjectSignaled(HANDLE object) { |
237 WSANETWORKEVENTS ev; | 732 WSANETWORKEVENTS ev; |
238 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) { | 733 if (WSAEnumNetworkEvents(socket_, accept_event_, &ev) == SOCKET_ERROR) { |
239 PLOG(ERROR) << "WSAEnumNetworkEvents()"; | 734 PLOG(ERROR) << "WSAEnumNetworkEvents()"; |
240 return; | 735 return; |
241 } | 736 } |
242 | 737 |
243 if (ev.lNetworkEvents & FD_ACCEPT) { | 738 if (ev.lNetworkEvents & FD_ACCEPT) { |
244 int result = AcceptInternal(accept_socket_, accept_address_); | 739 int result = AcceptInternal(accept_socket_, accept_address_); |
245 if (result != ERR_IO_PENDING) { | 740 if (result != ERR_IO_PENDING) { |
246 accept_socket_ = NULL; | 741 accept_socket_ = NULL; |
247 accept_address_ = NULL; | 742 accept_address_ = NULL; |
248 CompletionCallback callback = accept_callback_; | 743 base::ResetAndReturn(&accept_callback_).Run(result); |
249 accept_callback_.Reset(); | 744 } |
250 callback.Run(result); | 745 } |
251 } | 746 } |
252 } | 747 |
748 int TCPSocketWin::DoConnect() { | |
749 DCHECK_EQ(connect_os_error_, 0); | |
750 DCHECK(!core_); | |
751 | |
752 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | |
753 CreateNetLogIPEndPointCallback(peer_address_.get())); | |
754 | |
755 core_ = new Core(this); | |
wtc
2013/09/13 16:33:05
It is fine to create core_ lazily here. I forgot t
yzshen1
2013/09/13 18:16:44
Done.
| |
756 // WSAEventSelect sets the socket to non-blocking mode as a side effect. | |
757 // Our connect() and recv() calls require that the socket be non-blocking. | |
758 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT); | |
759 | |
760 SockaddrStorage storage; | |
761 if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) | |
762 return ERR_INVALID_ARGUMENT; | |
763 if (!connect(socket_, storage.addr, storage.addr_len)) { | |
764 // Connected without waiting! | |
765 // | |
766 // The MSDN page for connect says: | |
767 // With a nonblocking socket, the connection attempt cannot be completed | |
768 // immediately. In this case, connect will return SOCKET_ERROR, and | |
769 // WSAGetLastError will return WSAEWOULDBLOCK. | |
770 // which implies that for a nonblocking socket, connect never returns 0. | |
771 // It's not documented whether the event object will be signaled or not | |
772 // if connect does return 0. So the code below is essentially dead code | |
773 // and we don't know if it's correct. | |
774 NOTREACHED(); | |
775 | |
776 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) | |
777 return OK; | |
778 } else { | |
779 int os_error = WSAGetLastError(); | |
780 if (os_error != WSAEWOULDBLOCK) { | |
781 LOG(ERROR) << "connect failed: " << os_error; | |
782 connect_os_error_ = os_error; | |
783 return MapConnectError(os_error); | |
784 } | |
785 } | |
786 | |
787 core_->WatchForRead(); | |
788 return ERR_IO_PENDING; | |
789 } | |
790 | |
791 void TCPSocketWin::DoConnectComplete(int result) { | |
792 // Log the end of this attempt (and any OS error it threw). | |
793 int os_error = connect_os_error_; | |
794 connect_os_error_ = 0; | |
795 if (result != OK) { | |
796 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | |
797 NetLog::IntegerCallback("os_error", os_error)); | |
798 } else { | |
799 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); | |
800 } | |
801 | |
802 if (!logging_multiple_connect_attempts_) | |
803 LogConnectEnd(result); | |
804 } | |
805 | |
806 void TCPSocketWin::LogConnectBegin(const AddressList& addresses) { | |
807 base::StatsCounter connects("tcp.connect"); | |
808 connects.Increment(); | |
809 | |
810 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, | |
811 addresses.CreateNetLogCallback()); | |
812 } | |
813 | |
814 void TCPSocketWin::LogConnectEnd(int net_error) { | |
815 if (net_error == OK) | |
816 UpdateConnectionTypeHistograms(CONNECTION_ANY); | |
817 | |
818 if (net_error != OK) { | |
819 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); | |
820 return; | |
821 } | |
822 | |
823 struct sockaddr_storage source_address; | |
824 socklen_t addrlen = sizeof(source_address); | |
825 int rv = getsockname( | |
826 socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen); | |
827 if (rv != 0) { | |
828 LOG(ERROR) << "getsockname() [rv: " << rv | |
829 << "] error: " << WSAGetLastError(); | |
830 NOTREACHED(); | |
831 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); | |
832 return; | |
833 } | |
834 | |
835 net_log_.EndEvent( | |
836 NetLog::TYPE_TCP_CONNECT, | |
837 CreateNetLogSourceAddressCallback( | |
838 reinterpret_cast<const struct sockaddr*>(&source_address), | |
839 sizeof(source_address))); | |
840 } | |
841 | |
842 int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len, | |
843 const CompletionCallback& callback) { | |
844 if (!core_->non_blocking_reads_initialized_) { | |
845 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, | |
846 FD_READ | FD_CLOSE); | |
847 core_->non_blocking_reads_initialized_ = true; | |
848 } | |
849 int rv = recv(socket_, buf->data(), buf_len, 0); | |
850 if (rv == SOCKET_ERROR) { | |
851 int os_error = WSAGetLastError(); | |
852 if (os_error != WSAEWOULDBLOCK) { | |
853 int net_error = MapSystemError(os_error); | |
854 net_log_.AddEvent( | |
855 NetLog::TYPE_SOCKET_READ_ERROR, | |
856 CreateNetLogSocketErrorCallback(net_error, os_error)); | |
857 return net_error; | |
858 } | |
859 } else { | |
860 base::StatsCounter read_bytes("tcp.read_bytes"); | |
861 if (rv > 0) | |
862 read_bytes.Add(rv); | |
863 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, | |
864 buf->data()); | |
865 return rv; | |
866 } | |
867 | |
868 waiting_read_ = true; | |
869 read_callback_ = callback; | |
870 core_->read_iobuffer_ = buf; | |
871 core_->read_buffer_length_ = buf_len; | |
872 core_->WatchForRead(); | |
873 return ERR_IO_PENDING; | |
874 } | |
875 | |
876 void TCPSocketWin::DidCompleteConnect() { | |
877 DCHECK(waiting_connect_); | |
878 DCHECK(!read_callback_.is_null()); | |
879 int result; | |
880 | |
881 WSANETWORKEVENTS events; | |
882 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, | |
883 &events); | |
884 int os_error = 0; | |
885 if (rv == SOCKET_ERROR) { | |
886 NOTREACHED(); | |
887 os_error = WSAGetLastError(); | |
888 result = MapSystemError(os_error); | |
889 } else if (events.lNetworkEvents & FD_CONNECT) { | |
890 os_error = events.iErrorCode[FD_CONNECT_BIT]; | |
891 result = MapConnectError(os_error); | |
892 } else { | |
893 NOTREACHED(); | |
894 result = ERR_UNEXPECTED; | |
895 } | |
896 | |
897 connect_os_error_ = os_error; | |
898 DoConnectComplete(result); | |
899 waiting_connect_ = false; | |
900 | |
901 DCHECK_NE(result, ERR_IO_PENDING); | |
902 base::ResetAndReturn(&read_callback_).Run(result); | |
903 } | |
904 | |
905 void TCPSocketWin::DidCompleteWrite() { | |
906 DCHECK(waiting_write_); | |
907 DCHECK(!write_callback_.is_null()); | |
908 | |
909 DWORD num_bytes, flags; | |
910 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, | |
911 &num_bytes, FALSE, &flags); | |
912 WSAResetEvent(core_->write_overlapped_.hEvent); | |
913 waiting_write_ = false; | |
914 int rv; | |
915 if (!ok) { | |
916 int os_error = WSAGetLastError(); | |
917 rv = MapSystemError(os_error); | |
918 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, | |
919 CreateNetLogSocketErrorCallback(rv, os_error)); | |
920 } else { | |
921 rv = static_cast<int>(num_bytes); | |
922 if (rv > core_->write_buffer_length_ || rv < 0) { | |
923 // It seems that some winsock interceptors report that more was written | |
924 // than was available. Treat this as an error. http://crbug.com/27870 | |
925 LOG(ERROR) << "Detected broken LSP: Asked to write " | |
926 << core_->write_buffer_length_ << " bytes, but " << rv | |
927 << " bytes reported."; | |
928 rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; | |
929 } else { | |
930 base::StatsCounter write_bytes("tcp.write_bytes"); | |
931 write_bytes.Add(num_bytes); | |
932 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes, | |
933 core_->write_iobuffer_->data()); | |
934 } | |
935 } | |
936 | |
937 core_->write_iobuffer_ = NULL; | |
938 | |
939 DCHECK_NE(rv, ERR_IO_PENDING); | |
940 base::ResetAndReturn(&write_callback_).Run(rv); | |
941 } | |
942 | |
943 void TCPSocketWin::DidSignalRead() { | |
944 DCHECK(waiting_read_); | |
945 DCHECK(!read_callback_.is_null()); | |
946 | |
947 int os_error = 0; | |
948 WSANETWORKEVENTS network_events; | |
949 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, | |
950 &network_events); | |
951 if (rv == SOCKET_ERROR) { | |
952 os_error = WSAGetLastError(); | |
953 rv = MapSystemError(os_error); | |
954 } else if (network_events.lNetworkEvents) { | |
955 DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0); | |
956 // If network_events.lNetworkEvents is FD_CLOSE and | |
957 // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful | |
958 // connection closure. It is tempting to directly set rv to 0 in | |
959 // this case, but the MSDN pages for WSAEventSelect and | |
960 // WSAAsyncSelect recommend we still call DoRead(): | |
961 // FD_CLOSE should only be posted after all data is read from a | |
962 // socket, but an application should check for remaining data upon | |
963 // receipt of FD_CLOSE to avoid any possibility of losing data. | |
964 // | |
965 // If network_events.iErrorCode[FD_READ_BIT] or | |
966 // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call | |
967 // DoRead() because recv() reports a more accurate error code | |
968 // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was | |
969 // reset. | |
970 rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_, | |
971 read_callback_); | |
972 if (rv == ERR_IO_PENDING) | |
973 return; | |
974 } else { | |
975 // This may happen because Read() may succeed synchronously and | |
976 // consume all the received data without resetting the event object. | |
977 core_->WatchForRead(); | |
978 return; | |
979 } | |
980 | |
981 waiting_read_ = false; | |
982 core_->read_iobuffer_ = NULL; | |
983 core_->read_buffer_length_ = 0; | |
984 | |
985 DCHECK_NE(rv, ERR_IO_PENDING); | |
986 base::ResetAndReturn(&read_callback_).Run(rv); | |
253 } | 987 } |
254 | 988 |
255 } // namespace net | 989 } // namespace net |
990 | |
OLD | NEW |