| 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 | |
| 82 // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP | 52 // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP |
| 83 // connections. See http://crbug.com/27400 for details. | 53 // connections. See http://crbug.com/27400 for details. |
| 84 bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { | 54 bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) { |
| 85 unsigned delay = delay_secs * 1000; | 55 unsigned delay = delay_secs * 1000; |
| 86 struct tcp_keepalive keepalive_vals = { | 56 struct tcp_keepalive keepalive_vals = { |
| 87 enable ? 1u : 0u, // TCP keep-alive on. | 57 enable ? 1u : 0u, // TCP keep-alive on. |
| 88 delay, // Delay seconds before sending first TCP keep-alive packet. | 58 delay, // Delay seconds before sending first TCP keep-alive packet. |
| 89 delay, // Delay seconds between sending TCP keep-alive packets. | 59 delay, // Delay seconds between sending TCP keep-alive packets. |
| 90 }; | 60 }; |
| 91 DWORD bytes_returned = 0xABAB; | 61 DWORD bytes_returned = 0xABAB; |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 return ERR_SOCKET_NOT_CONNECTED; | 542 return ERR_SOCKET_NOT_CONNECTED; |
| 573 *address = *peer_address_; | 543 *address = *peer_address_; |
| 574 return OK; | 544 return OK; |
| 575 } | 545 } |
| 576 | 546 |
| 577 int TCPSocketWin::SetDefaultOptionsForServer() { | 547 int TCPSocketWin::SetDefaultOptionsForServer() { |
| 578 return SetExclusiveAddrUse(); | 548 return SetExclusiveAddrUse(); |
| 579 } | 549 } |
| 580 | 550 |
| 581 void TCPSocketWin::SetDefaultOptionsForClient() { | 551 void TCPSocketWin::SetDefaultOptionsForClient() { |
| 582 DisableNagle(socket_, true); | 552 SetTCPNoDelay(socket_, /*no_delay=*/true); |
| 583 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); | 553 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); |
| 584 } | 554 } |
| 585 | 555 |
| 586 int TCPSocketWin::SetExclusiveAddrUse() { | 556 int TCPSocketWin::SetExclusiveAddrUse() { |
| 587 // On Windows, a bound end point can be hijacked by another process by | 557 // On Windows, a bound end point can be hijacked by another process by |
| 588 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE | 558 // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE |
| 589 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the | 559 // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the |
| 590 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another | 560 // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another |
| 591 // socket to forcibly bind to the end point until the end point is unbound. | 561 // socket to forcibly bind to the end point until the end point is unbound. |
| 592 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. | 562 // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 617 int TCPSocketWin::SetSendBufferSize(int32_t size) { | 587 int TCPSocketWin::SetSendBufferSize(int32_t size) { |
| 618 DCHECK(CalledOnValidThread()); | 588 DCHECK(CalledOnValidThread()); |
| 619 return SetSocketSendBufferSize(socket_, size); | 589 return SetSocketSendBufferSize(socket_, size); |
| 620 } | 590 } |
| 621 | 591 |
| 622 bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { | 592 bool TCPSocketWin::SetKeepAlive(bool enable, int delay) { |
| 623 return SetTCPKeepAlive(socket_, enable, delay); | 593 return SetTCPKeepAlive(socket_, enable, delay); |
| 624 } | 594 } |
| 625 | 595 |
| 626 bool TCPSocketWin::SetNoDelay(bool no_delay) { | 596 bool TCPSocketWin::SetNoDelay(bool no_delay) { |
| 627 return DisableNagle(socket_, no_delay); | 597 return SetTCPNoDelay(socket_, no_delay); |
| 628 } | 598 } |
| 629 | 599 |
| 630 void TCPSocketWin::Close() { | 600 void TCPSocketWin::Close() { |
| 631 DCHECK(CalledOnValidThread()); | 601 DCHECK(CalledOnValidThread()); |
| 632 | 602 |
| 633 if (socket_ != INVALID_SOCKET) { | 603 if (socket_ != INVALID_SOCKET) { |
| 634 // Only log the close event if there's actually a socket to close. | 604 // Only log the close event if there's actually a socket to close. |
| 635 net_log_.AddEvent(NetLog::EventType::TYPE_SOCKET_CLOSED); | 605 net_log_.AddEvent(NetLog::EventType::TYPE_SOCKET_CLOSED); |
| 636 | 606 |
| 637 // Note: don't use CancelIo to cancel pending IO because it doesn't work | 607 // 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... |
| 1034 } | 1004 } |
| 1035 | 1005 |
| 1036 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { | 1006 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { |
| 1037 DCHECK(out_rtt); | 1007 DCHECK(out_rtt); |
| 1038 // TODO(bmcquade): Consider implementing using | 1008 // TODO(bmcquade): Consider implementing using |
| 1039 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. | 1009 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. |
| 1040 return false; | 1010 return false; |
| 1041 } | 1011 } |
| 1042 | 1012 |
| 1043 } // namespace net | 1013 } // namespace net |
| OLD | NEW |