OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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_client_socket_win.h" | 5 #include "net/socket/tcp_client_socket_win.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/memory_debug.h" | 9 #include "base/memory_debug.h" |
| 10 #include "base/stats_counters.h" |
10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
11 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
12 #include "base/trace_event.h" | 13 #include "base/trace_event.h" |
13 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
14 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
15 #include "net/base/winsock_init.h" | 16 #include "net/base/winsock_init.h" |
16 | 17 |
17 namespace net { | 18 namespace net { |
18 | 19 |
19 namespace { | 20 namespace { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 | 233 |
233 TCPClientSocketWin::~TCPClientSocketWin() { | 234 TCPClientSocketWin::~TCPClientSocketWin() { |
234 Disconnect(); | 235 Disconnect(); |
235 } | 236 } |
236 | 237 |
237 int TCPClientSocketWin::Connect(CompletionCallback* callback) { | 238 int TCPClientSocketWin::Connect(CompletionCallback* callback) { |
238 // If already connected, then just return OK. | 239 // If already connected, then just return OK. |
239 if (socket_ != INVALID_SOCKET) | 240 if (socket_ != INVALID_SOCKET) |
240 return OK; | 241 return OK; |
241 | 242 |
| 243 static StatsCounter connects("tcp.connect"); |
| 244 connects.Increment(); |
| 245 |
242 TRACE_EVENT_BEGIN("socket.connect", this, ""); | 246 TRACE_EVENT_BEGIN("socket.connect", this, ""); |
243 const struct addrinfo* ai = current_ai_; | 247 const struct addrinfo* ai = current_ai_; |
244 DCHECK(ai); | 248 DCHECK(ai); |
245 | 249 |
246 int rv = CreateSocket(ai); | 250 int rv = CreateSocket(ai); |
247 if (rv != OK) | 251 if (rv != OK) |
248 return rv; | 252 return rv; |
249 | 253 |
250 DCHECK(!core_); | 254 DCHECK(!core_); |
251 core_ = new Core(this); | 255 core_ = new Core(this); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { | 383 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { |
380 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num)); | 384 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num)); |
381 | 385 |
382 // Because of how WSARecv fills memory when used asynchronously, Purify | 386 // Because of how WSARecv fills memory when used asynchronously, Purify |
383 // isn't able to detect that it's been initialized, so it scans for 0xcd | 387 // isn't able to detect that it's been initialized, so it scans for 0xcd |
384 // in the buffer and reports UMRs (uninitialized memory reads) for those | 388 // in the buffer and reports UMRs (uninitialized memory reads) for those |
385 // individual bytes. We override that in PURIFY builds to avoid the | 389 // individual bytes. We override that in PURIFY builds to avoid the |
386 // false error reports. | 390 // false error reports. |
387 // See bug 5297. | 391 // See bug 5297. |
388 base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num); | 392 base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num); |
| 393 static StatsCounter read_bytes("tcp.read_bytes"); |
| 394 read_bytes.Add(num); |
389 return static_cast<int>(num); | 395 return static_cast<int>(num); |
390 } | 396 } |
391 } else { | 397 } else { |
392 int err = WSAGetLastError(); | 398 int err = WSAGetLastError(); |
393 if (err != WSA_IO_PENDING) | 399 if (err != WSA_IO_PENDING) |
394 return MapWinsockError(err); | 400 return MapWinsockError(err); |
395 } | 401 } |
396 core_->WatchForRead(); | 402 core_->WatchForRead(); |
397 waiting_read_ = true; | 403 waiting_read_ = true; |
398 read_callback_ = callback; | 404 read_callback_ = callback; |
399 core_->read_iobuffer_ = buf; | 405 core_->read_iobuffer_ = buf; |
400 return ERR_IO_PENDING; | 406 return ERR_IO_PENDING; |
401 } | 407 } |
402 | 408 |
403 int TCPClientSocketWin::Write(IOBuffer* buf, | 409 int TCPClientSocketWin::Write(IOBuffer* buf, |
404 int buf_len, | 410 int buf_len, |
405 CompletionCallback* callback) { | 411 CompletionCallback* callback) { |
406 DCHECK_NE(socket_, INVALID_SOCKET); | 412 DCHECK_NE(socket_, INVALID_SOCKET); |
407 DCHECK(!waiting_write_); | 413 DCHECK(!waiting_write_); |
408 DCHECK(!write_callback_); | 414 DCHECK(!write_callback_); |
409 DCHECK_GT(buf_len, 0); | 415 DCHECK_GT(buf_len, 0); |
410 DCHECK(!core_->write_iobuffer_); | 416 DCHECK(!core_->write_iobuffer_); |
411 | 417 |
| 418 static StatsCounter reads("tcp.writes"); |
| 419 reads.Increment(); |
| 420 |
412 core_->write_buffer_.len = buf_len; | 421 core_->write_buffer_.len = buf_len; |
413 core_->write_buffer_.buf = buf->data(); | 422 core_->write_buffer_.buf = buf->data(); |
414 | 423 |
415 TRACE_EVENT_BEGIN("socket.write", this, ""); | 424 TRACE_EVENT_BEGIN("socket.write", this, ""); |
416 // TODO(wtc): Remove the CHECK after enough testing. | 425 // TODO(wtc): Remove the CHECK after enough testing. |
417 CHECK( | 426 CHECK( |
418 WaitForSingleObject(core_->write_overlapped_.hEvent, 0) == WAIT_TIMEOUT); | 427 WaitForSingleObject(core_->write_overlapped_.hEvent, 0) == WAIT_TIMEOUT); |
419 DWORD num; | 428 DWORD num; |
420 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, | 429 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, |
421 &core_->write_overlapped_, NULL); | 430 &core_->write_overlapped_, NULL); |
422 if (rv == 0) { | 431 if (rv == 0) { |
423 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { | 432 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { |
424 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num)); | 433 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num)); |
| 434 static StatsCounter write_bytes("tcp.write_bytes"); |
| 435 write_bytes.Add(num); |
425 return static_cast<int>(num); | 436 return static_cast<int>(num); |
426 } | 437 } |
427 } else { | 438 } else { |
428 int err = WSAGetLastError(); | 439 int err = WSAGetLastError(); |
429 if (err != WSA_IO_PENDING) | 440 if (err != WSA_IO_PENDING) |
430 return MapWinsockError(err); | 441 return MapWinsockError(err); |
431 } | 442 } |
432 core_->WatchForWrite(); | 443 core_->WatchForWrite(); |
433 waiting_write_ = true; | 444 waiting_write_ = true; |
434 write_callback_ = callback; | 445 write_callback_ = callback; |
435 core_->write_iobuffer_ = buf; | 446 core_->write_iobuffer_ = buf; |
436 return ERR_IO_PENDING; | 447 return ERR_IO_PENDING; |
437 } | 448 } |
438 | 449 |
| 450 bool TCPClientSocketWin::SetReceiveBufferSize(int32 size) { |
| 451 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 452 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 453 DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError(); |
| 454 return rv == 0; |
| 455 } |
| 456 |
| 457 bool TCPClientSocketWin::SetSendBufferSize(int32 size) { |
| 458 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 459 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 460 DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError(); |
| 461 return rv == 0; |
| 462 } |
| 463 |
439 int TCPClientSocketWin::CreateSocket(const struct addrinfo* ai) { | 464 int TCPClientSocketWin::CreateSocket(const struct addrinfo* ai) { |
440 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, | 465 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, |
441 WSA_FLAG_OVERLAPPED); | 466 WSA_FLAG_OVERLAPPED); |
442 if (socket_ == INVALID_SOCKET) { | 467 if (socket_ == INVALID_SOCKET) { |
443 DWORD err = WSAGetLastError(); | 468 DWORD err = WSAGetLastError(); |
444 LOG(ERROR) << "WSASocket failed: " << err; | 469 LOG(ERROR) << "WSASocket failed: " << err; |
445 return MapWinsockError(err); | 470 return MapWinsockError(err); |
446 } | 471 } |
447 | 472 |
448 // Increase the socket buffer sizes from the default sizes for WinXP. In | 473 // Increase the socket buffer sizes from the default sizes for WinXP. In |
449 // performance testing, there is substantial benefit by increasing from 8KB | 474 // performance testing, there is substantial benefit by increasing from 8KB |
450 // to 64KB. | 475 // to 64KB. |
451 // See also: | 476 // See also: |
452 // http://support.microsoft.com/kb/823764/EN-US | 477 // http://support.microsoft.com/kb/823764/EN-US |
453 // On Vista, if we manually set these sizes, Vista turns off its receive | 478 // On Vista, if we manually set these sizes, Vista turns off its receive |
454 // window auto-tuning feature. | 479 // window auto-tuning feature. |
455 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx | 480 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx |
456 // Since Vista's auto-tune is better than any static value we can could set, | 481 // Since Vista's auto-tune is better than any static value we can could set, |
457 // only change these on pre-vista machines. | 482 // only change these on pre-vista machines. |
458 int32 major_version, minor_version, fix_version; | 483 int32 major_version, minor_version, fix_version; |
459 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, | 484 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, |
460 &fix_version); | 485 &fix_version); |
461 if (major_version < 6) { | 486 if (major_version < 6) { |
462 const int kSocketBufferSize = 64 * 1024; | 487 const int32 kSocketBufferSize = 64 * 1024; |
463 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 488 SetReceiveBufferSize(kSocketBufferSize); |
464 reinterpret_cast<const char*>(&kSocketBufferSize), | 489 SetSendBufferSize(kSocketBufferSize); |
465 sizeof(kSocketBufferSize)); | |
466 DCHECK(!rv) << "Could not set socket send buffer size"; | |
467 rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | |
468 reinterpret_cast<const char*>(&kSocketBufferSize), | |
469 sizeof(kSocketBufferSize)); | |
470 DCHECK(!rv) << "Could not set socket receive buffer size"; | |
471 } | 490 } |
472 | 491 |
473 // Disable Nagle. | 492 // Disable Nagle. |
474 // The Nagle implementation on windows is governed by RFC 896. The idea | 493 // The Nagle implementation on windows is governed by RFC 896. The idea |
475 // behind Nagle is to reduce small packets on the network. When Nagle is | 494 // behind Nagle is to reduce small packets on the network. When Nagle is |
476 // enabled, if a partial packet has been sent, the TCP stack will disallow | 495 // enabled, if a partial packet has been sent, the TCP stack will disallow |
477 // further *partial* packets until an ACK has been received from the other | 496 // further *partial* packets until an ACK has been received from the other |
478 // side. Good applications should always strive to send as much data as | 497 // side. Good applications should always strive to send as much data as |
479 // possible and avoid partial-packet sends. However, in most real world | 498 // possible and avoid partial-packet sends. However, in most real world |
480 // applications, there are edge cases where this does not happen, and two | 499 // applications, there are edge cases where this does not happen, and two |
(...skipping 16 matching lines...) Expand all Loading... |
497 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle)); | 516 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle)); |
498 DCHECK(!rv) << "Could not disable nagle"; | 517 DCHECK(!rv) << "Could not disable nagle"; |
499 | 518 |
500 return OK; | 519 return OK; |
501 } | 520 } |
502 | 521 |
503 void TCPClientSocketWin::DoReadCallback(int rv) { | 522 void TCPClientSocketWin::DoReadCallback(int rv) { |
504 DCHECK_NE(rv, ERR_IO_PENDING); | 523 DCHECK_NE(rv, ERR_IO_PENDING); |
505 DCHECK(read_callback_); | 524 DCHECK(read_callback_); |
506 | 525 |
| 526 static StatsCounter read_bytes("tcp.read_bytes"); |
| 527 read_bytes.Add(rv); |
| 528 |
507 // since Run may result in Read being called, clear read_callback_ up front. | 529 // since Run may result in Read being called, clear read_callback_ up front. |
508 CompletionCallback* c = read_callback_; | 530 CompletionCallback* c = read_callback_; |
509 read_callback_ = NULL; | 531 read_callback_ = NULL; |
510 c->Run(rv); | 532 c->Run(rv); |
511 } | 533 } |
512 | 534 |
513 void TCPClientSocketWin::DoWriteCallback(int rv) { | 535 void TCPClientSocketWin::DoWriteCallback(int rv) { |
514 DCHECK_NE(rv, ERR_IO_PENDING); | 536 DCHECK_NE(rv, ERR_IO_PENDING); |
515 DCHECK(write_callback_); | 537 DCHECK(write_callback_); |
516 | 538 |
| 539 static StatsCounter write_bytes("tcp.write_bytes"); |
| 540 write_bytes.Add(rv); |
| 541 |
517 // since Run may result in Write being called, clear write_callback_ up front. | 542 // since Run may result in Write being called, clear write_callback_ up front. |
518 CompletionCallback* c = write_callback_; | 543 CompletionCallback* c = write_callback_; |
519 write_callback_ = NULL; | 544 write_callback_ = NULL; |
520 c->Run(rv); | 545 c->Run(rv); |
521 } | 546 } |
522 | 547 |
523 void TCPClientSocketWin::DidCompleteConnect() { | 548 void TCPClientSocketWin::DidCompleteConnect() { |
524 DCHECK(waiting_connect_); | 549 DCHECK(waiting_connect_); |
525 int result; | 550 int result; |
526 | 551 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, | 603 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, |
579 &num_bytes, FALSE, &flags); | 604 &num_bytes, FALSE, &flags); |
580 WSAResetEvent(core_->write_overlapped_.hEvent); | 605 WSAResetEvent(core_->write_overlapped_.hEvent); |
581 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes)); | 606 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes)); |
582 waiting_write_ = false; | 607 waiting_write_ = false; |
583 core_->write_iobuffer_ = NULL; | 608 core_->write_iobuffer_ = NULL; |
584 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError())); | 609 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError())); |
585 } | 610 } |
586 | 611 |
587 } // namespace net | 612 } // namespace net |
OLD | NEW |