Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: net/socket/tcp_socket_win.cc

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

Powered by Google App Engine
This is Rietveld 408576698