| 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.h" | 5 #include "net/socket/tcp_socket.h" |
| 6 #include "net/socket/tcp_socket_win.h" | 6 #include "net/socket/tcp_socket_win.h" |
| 7 | 7 |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <mstcpip.h> | 9 #include <mstcpip.h> |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 int SetSocketSendBufferSize(SOCKET socket, int32_t size) { | 43 int SetSocketSendBufferSize(SOCKET socket, int32_t size) { |
| 44 int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, | 44 int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, |
| 45 reinterpret_cast<const char*>(&size), sizeof(size)); | 45 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 46 int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError()); | 46 int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError()); |
| 47 DCHECK(!rv) << "Could not set socket send buffer size: " << net_error; | 47 DCHECK(!rv) << "Could not set socket send buffer size: " << net_error; |
| 48 return net_error; | 48 return net_error; |
| 49 } | 49 } |
| 50 | 50 |
| 51 // Disable Nagle. | 51 // Disable Nagle. |
| 52 // The Nagle implementation on windows is governed by RFC 896. The idea |
| 53 // behind Nagle is to reduce small packets on the network. When Nagle is |
| 54 // enabled, if a partial packet has been sent, the TCP stack will disallow |
| 55 // further *partial* packets until an ACK has been received from the other |
| 56 // side. Good applications should always strive to send as much data as |
| 57 // possible and avoid partial-packet sends. However, in most real world |
| 58 // applications, there are edge cases where this does not happen, and two |
| 59 // partial packets may be sent back to back. For a browser, it is NEVER |
| 60 // a benefit to delay for an RTT before the second packet is sent. |
| 61 // |
| 62 // As a practical example in Chromium today, consider the case of a small |
| 63 // POST. I have verified this: |
| 64 // Client writes 649 bytes of header (partial packet #1) |
| 65 // Client writes 50 bytes of POST data (partial packet #2) |
| 66 // In the above example, with Nagle, a RTT delay is inserted between these |
| 67 // two sends due to nagle. RTTs can easily be 100ms or more. The best |
| 68 // fix is to make sure that for POSTing data, we write as much data as |
| 69 // possible and minimize partial packets. We will fix that. But disabling |
| 70 // Nagle also ensure we don't run into this delay in other edge cases. |
| 71 // See also: |
| 72 // http://technet.microsoft.com/en-us/library/bb726981.aspx |
| 73 bool DisableNagle(SOCKET socket, bool disable) { |
| 74 BOOL val = disable ? TRUE : FALSE; |
| 75 int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, |
| 76 reinterpret_cast<const char*>(&val), |
| 77 sizeof(val)); |
| 78 DCHECK(!rv) << "Could not disable nagle"; |
| 79 return rv == 0; |
| 80 } |
| 81 |
| 52 // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP | 82 // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP |
| 53 // connections. See http://crbug.com/27400 for details. | 83 // connections. See http://crbug.com/27400 for details. |
| 54 bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { | 84 bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { |
| 55 unsigned delay = delay_secs * 1000; | 85 unsigned delay = delay_secs * 1000; |
| 56 struct tcp_keepalive keepalive_vals = { | 86 struct tcp_keepalive keepalive_vals = { |
| 57 enable ? 1u : 0u, // TCP keep-alive on. | 87 enable ? 1u : 0u, // TCP keep-alive on. |
| 58 delay, // Delay seconds before sending first TCP keep-alive packet. | 88 delay, // Delay seconds before sending first TCP keep-alive packet. |
| 59 delay, // Delay seconds between sending TCP keep-alive packets. | 89 delay, // Delay seconds between sending TCP keep-alive packets. |
| 60 }; | 90 }; |
| 61 DWORD bytes_returned = 0xABAB; | 91 DWORD bytes_returned = 0xABAB; |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 return ERR_SOCKET_NOT_CONNECTED; | 572 return ERR_SOCKET_NOT_CONNECTED; |
| 543 *address = *peer_address_; | 573 *address = *peer_address_; |
| 544 return OK; | 574 return OK; |
| 545 } | 575 } |
| 546 | 576 |
| 547 int TCPSocketWin::SetDefaultOptionsForServer() { | 577 int TCPSocketWin::SetDefaultOptionsForServer() { |
| 548 return SetExclusiveAddrUse(); | 578 return SetExclusiveAddrUse(); |
| 549 } | 579 } |
| 550 | 580 |
| 551 void TCPSocketWin::SetDefaultOptionsForClient() { | 581 void TCPSocketWin::SetDefaultOptionsForClient() { |
| 552 SetTCPNoDelay(socket_, /*no_delay=*/true); | 582 DisableNagle(socket_, true); |
| 553 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); | 583 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); |
| 554 } | 584 } |
| 555 | 585 |
| 556 int TCPSocketWin::SetExclusiveAddrUse() { | 586 int TCPSocketWin::SetExclusiveAddrUse() { |
| 557 // On Windows, a bound end point can be hijacked by another process by | 587 // On Windows, a bound end point can be hijacked by another process by |
| 558 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE | 588 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE |
| 559 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the | 589 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the |
| 560 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another | 590 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another |
| 561 // socket to forcibly bind to the end point until the end point is unbound. | 591 // socket to forcibly bind to the end point until the end point is unbound. |
| 562 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. | 592 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 587 int TCPSocketWin::SetSendBufferSize(int32_t size) { | 617 int TCPSocketWin::SetSendBufferSize(int32_t size) { |
| 588 DCHECK(CalledOnValidThread()); | 618 DCHECK(CalledOnValidThread()); |
| 589 return SetSocketSendBufferSize(socket_, size); | 619 return SetSocketSendBufferSize(socket_, size); |
| 590 } | 620 } |
| 591 | 621 |
| 592 bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { | 622 bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { |
| 593 return SetTCPKeepAlive(socket_, enable, delay); | 623 return SetTCPKeepAlive(socket_, enable, delay); |
| 594 } | 624 } |
| 595 | 625 |
| 596 bool TCPSocketWin::SetNoDelay(bool no_delay) { | 626 bool TCPSocketWin::SetNoDelay(bool no_delay) { |
| 597 return SetTCPNoDelay(socket_, no_delay); | 627 return DisableNagle(socket_, no_delay); |
| 598 } | 628 } |
| 599 | 629 |
| 600 void TCPSocketWin::Close() { | 630 void TCPSocketWin::Close() { |
| 601 DCHECK(CalledOnValidThread()); | 631 DCHECK(CalledOnValidThread()); |
| 602 | 632 |
| 603 if (socket_ != INVALID_SOCKET) { | 633 if (socket_ != INVALID_SOCKET) { |
| 604 // Only log the close event if there's actually a socket to close. | 634 // Only log the close event if there's actually a socket to close. |
| 605 net_log_.AddEvent(NetLog::EventType::TYPE_SOCKET_CLOSED); | 635 net_log_.AddEvent(NetLog::EventType::TYPE_SOCKET_CLOSED); |
| 606 | 636 |
| 607 // Note: don't use CancelIo to cancel pending IO because it doesn't work | 637 // Note: don't use CancelIo to cancel pending IO because it doesn't work |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 } | 1034 } |
| 1005 | 1035 |
| 1006 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { | 1036 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { |
| 1007 DCHECK(out_rtt); | 1037 DCHECK(out_rtt); |
| 1008 // TODO(bmcquade): Consider implementing using | 1038 // TODO(bmcquade): Consider implementing using |
| 1009 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. | 1039 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. |
| 1010 return false; | 1040 return false; |
| 1011 } | 1041 } |
| 1012 | 1042 |
| 1013 } // namespace net | 1043 } // namespace net |
| OLD | NEW |