| 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 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <netinet/tcp.h> | 8 #include <netinet/tcp.h> |
| 9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/posix/eintr_wrapper.h" | 16 #include "base/posix/eintr_wrapper.h" |
| 17 #include "base/profiler/scoped_tracker.h" |
| 17 #include "base/task_runner_util.h" | 18 #include "base/task_runner_util.h" |
| 18 #include "base/threading/worker_pool.h" | 19 #include "base/threading/worker_pool.h" |
| 19 #include "net/base/address_list.h" | 20 #include "net/base/address_list.h" |
| 20 #include "net/base/connection_type_histograms.h" | 21 #include "net/base/connection_type_histograms.h" |
| 21 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
| 22 #include "net/base/ip_endpoint.h" | 23 #include "net/base/ip_endpoint.h" |
| 23 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 24 #include "net/base/network_activity_monitor.h" | 25 #include "net/base/network_activity_monitor.h" |
| 25 #include "net/base/network_change_notifier.h" | 26 #include "net/base/network_change_notifier.h" |
| 26 #include "net/base/sockaddr_storage.h" | 27 #include "net/base/sockaddr_storage.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { | 130 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { |
| 130 #if defined(OS_LINUX) || defined(OS_ANDROID) | 131 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 131 base::PostTaskAndReplyWithResult( | 132 base::PostTaskAndReplyWithResult( |
| 132 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), | 133 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), |
| 133 FROM_HERE, | 134 FROM_HERE, |
| 134 base::Bind(SystemSupportsTCPFastOpen), | 135 base::Bind(SystemSupportsTCPFastOpen), |
| 135 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); | 136 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); |
| 136 #endif | 137 #endif |
| 137 } | 138 } |
| 138 | 139 |
| 139 TCPSocketPosix::TCPSocketPosix(NetLog* net_log, const NetLog::Source& source) | 140 TCPSocketPosix::TCPSocketPosix( |
| 140 : use_tcp_fastopen_(false), | 141 scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher, |
| 142 NetLog* net_log, |
| 143 const NetLog::Source& source) |
| 144 : socket_performance_watcher_(std::move(socket_performance_watcher)), |
| 145 use_tcp_fastopen_(false), |
| 141 tcp_fastopen_write_attempted_(false), | 146 tcp_fastopen_write_attempted_(false), |
| 142 tcp_fastopen_connected_(false), | 147 tcp_fastopen_connected_(false), |
| 143 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), | 148 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), |
| 144 logging_multiple_connect_attempts_(false), | 149 logging_multiple_connect_attempts_(false), |
| 145 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 150 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
| 146 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 151 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 147 source.ToEventParametersCallback()); | 152 source.ToEventParametersCallback()); |
| 148 } | 153 } |
| 149 | 154 |
| 150 TCPSocketPosix::~TCPSocketPosix() { | 155 TCPSocketPosix::~TCPSocketPosix() { |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 IPEndPoint* address) { | 508 IPEndPoint* address) { |
| 504 DCHECK(accept_socket_); | 509 DCHECK(accept_socket_); |
| 505 | 510 |
| 506 SockaddrStorage storage; | 511 SockaddrStorage storage; |
| 507 if (accept_socket_->GetPeerAddress(&storage) != OK || | 512 if (accept_socket_->GetPeerAddress(&storage) != OK || |
| 508 !address->FromSockAddr(storage.addr, storage.addr_len)) { | 513 !address->FromSockAddr(storage.addr, storage.addr_len)) { |
| 509 accept_socket_.reset(); | 514 accept_socket_.reset(); |
| 510 return ERR_ADDRESS_INVALID; | 515 return ERR_ADDRESS_INVALID; |
| 511 } | 516 } |
| 512 | 517 |
| 513 tcp_socket->reset(new TCPSocketPosix(net_log_.net_log(), net_log_.source())); | 518 tcp_socket->reset( |
| 519 new TCPSocketPosix(nullptr, net_log_.net_log(), net_log_.source())); |
| 514 (*tcp_socket)->socket_.reset(accept_socket_.release()); | 520 (*tcp_socket)->socket_.reset(accept_socket_.release()); |
| 515 return OK; | 521 return OK; |
| 516 } | 522 } |
| 517 | 523 |
| 518 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, | 524 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, |
| 519 int rv) const { | 525 int rv) { |
| 520 DCHECK_NE(ERR_IO_PENDING, rv); | 526 DCHECK_NE(ERR_IO_PENDING, rv); |
| 527 NotifySocketPerformanceWatcher(); |
| 521 callback.Run(HandleConnectCompleted(rv)); | 528 callback.Run(HandleConnectCompleted(rv)); |
| 522 } | 529 } |
| 523 | 530 |
| 524 int TCPSocketPosix::HandleConnectCompleted(int rv) const { | 531 int TCPSocketPosix::HandleConnectCompleted(int rv) const { |
| 525 // Log the end of this attempt (and any OS error it threw). | 532 // Log the end of this attempt (and any OS error it threw). |
| 526 if (rv != OK) { | 533 if (rv != OK) { |
| 527 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | 534 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, |
| 528 NetLog::IntCallback("os_error", errno)); | 535 NetLog::IntCallback("os_error", errno)); |
| 529 } else { | 536 } else { |
| 530 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); | 537 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 | 571 |
| 565 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, | 572 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, |
| 566 CreateNetLogSourceAddressCallback(storage.addr, | 573 CreateNetLogSourceAddressCallback(storage.addr, |
| 567 storage.addr_len)); | 574 storage.addr_len)); |
| 568 } | 575 } |
| 569 | 576 |
| 570 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf, | 577 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf, |
| 571 const CompletionCallback& callback, | 578 const CompletionCallback& callback, |
| 572 int rv) { | 579 int rv) { |
| 573 DCHECK_NE(ERR_IO_PENDING, rv); | 580 DCHECK_NE(ERR_IO_PENDING, rv); |
| 581 NotifySocketPerformanceWatcher(); |
| 574 callback.Run(HandleReadCompleted(buf.get(), rv)); | 582 callback.Run(HandleReadCompleted(buf.get(), rv)); |
| 575 } | 583 } |
| 576 | 584 |
| 577 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) { | 585 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) { |
| 578 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 586 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 579 // A TCP FastOpen connect-with-write was attempted. This read was a | 587 // A TCP FastOpen connect-with-write was attempted. This read was a |
| 580 // subsequent read, which either succeeded or failed. If the read | 588 // subsequent read, which either succeeded or failed. If the read |
| 581 // succeeded, the socket is considered connected via TCP FastOpen. | 589 // succeeded, the socket is considered connected via TCP FastOpen. |
| 582 // If the read failed, TCP FastOpen is (conservatively) turned off for all | 590 // If the read failed, TCP FastOpen is (conservatively) turned off for all |
| 583 // subsequent connections. TCP FastOpen status is recorded in both cases. | 591 // subsequent connections. TCP FastOpen status is recorded in both cases. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 601 buf->data()); | 609 buf->data()); |
| 602 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); | 610 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); |
| 603 | 611 |
| 604 return rv; | 612 return rv; |
| 605 } | 613 } |
| 606 | 614 |
| 607 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, | 615 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, |
| 608 const CompletionCallback& callback, | 616 const CompletionCallback& callback, |
| 609 int rv) { | 617 int rv) { |
| 610 DCHECK_NE(ERR_IO_PENDING, rv); | 618 DCHECK_NE(ERR_IO_PENDING, rv); |
| 619 NotifySocketPerformanceWatcher(); |
| 611 callback.Run(HandleWriteCompleted(buf.get(), rv)); | 620 callback.Run(HandleWriteCompleted(buf.get(), rv)); |
| 612 } | 621 } |
| 613 | 622 |
| 614 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) { | 623 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) { |
| 615 if (rv < 0) { | 624 if (rv < 0) { |
| 616 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 625 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 617 // TCP FastOpen connect-with-write was attempted, and the write failed | 626 // TCP FastOpen connect-with-write was attempted, and the write failed |
| 618 // for unknown reasons. Record status and (conservatively) turn off | 627 // for unknown reasons. Record status and (conservatively) turn off |
| 619 // TCP FastOpen for all subsequent connections. | 628 // TCP FastOpen for all subsequent connections. |
| 620 // TODO (jri): This currently results in conservative behavior, where TCP | 629 // TODO (jri): This currently results in conservative behavior, where TCP |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 // turning off TCP FastOpen on more specific errors. | 697 // turning off TCP FastOpen on more specific errors. |
| 689 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; | 698 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; |
| 690 g_tcp_fastopen_has_failed = true; | 699 g_tcp_fastopen_has_failed = true; |
| 691 return rv; | 700 return rv; |
| 692 } | 701 } |
| 693 | 702 |
| 694 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; | 703 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; |
| 695 return socket_->WaitForWrite(buf, buf_len, callback); | 704 return socket_->WaitForWrite(buf, buf_len, callback); |
| 696 } | 705 } |
| 697 | 706 |
| 707 void TCPSocketPosix::NotifySocketPerformanceWatcher() { |
| 708 #if defined(TCP_INFO) |
| 709 // TODO(tbansal): Remove ScopedTracker once crbug.com/590254 is fixed. |
| 710 tracked_objects::ScopedTracker tracking_profile( |
| 711 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 712 "590254 TCPSocketPosix::NotifySocketPerformanceWatcher")); |
| 713 |
| 714 // Check if |socket_performance_watcher_| is interested in receiving a RTT |
| 715 // update notification. |
| 716 if (!socket_performance_watcher_ || |
| 717 !socket_performance_watcher_->ShouldNotifyUpdatedRTT()) { |
| 718 return; |
| 719 } |
| 720 |
| 721 tcp_info info; |
| 722 if (!GetTcpInfo(socket_->socket_fd(), &info)) |
| 723 return; |
| 724 |
| 725 // Only notify the |socket_performance_watcher_| if the RTT in |tcp_info| |
| 726 // struct was populated. A value of 0 may be valid in certain cases |
| 727 // (on very fast networks), but it is discarded. This means that |
| 728 // some of the RTT values may be missed, but the values that are kept are |
| 729 // guaranteed to be correct. |
| 730 if (info.tcpi_rtt == 0 && info.tcpi_rttvar == 0) |
| 731 return; |
| 732 |
| 733 socket_performance_watcher_->OnUpdatedRTTAvailable( |
| 734 base::TimeDelta::FromMicroseconds(info.tcpi_rtt)); |
| 735 #endif // defined(TCP_INFO) |
| 736 } |
| 737 |
| 698 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { | 738 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { |
| 699 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || | 739 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || |
| 700 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); | 740 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); |
| 701 | 741 |
| 702 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 742 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 703 // TCP FastOpen connect-with-write was attempted, and failed. | 743 // TCP FastOpen connect-with-write was attempted, and failed. |
| 704 tcp_fastopen_status_ = | 744 tcp_fastopen_status_ = |
| 705 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? | 745 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? |
| 706 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : | 746 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : |
| 707 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); | 747 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 if (info.tcpi_rtt > 0) { | 789 if (info.tcpi_rtt > 0) { |
| 750 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); | 790 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); |
| 751 return true; | 791 return true; |
| 752 } | 792 } |
| 753 } | 793 } |
| 754 #endif // defined(TCP_INFO) | 794 #endif // defined(TCP_INFO) |
| 755 return false; | 795 return false; |
| 756 } | 796 } |
| 757 | 797 |
| 758 } // namespace net | 798 } // namespace net |
| OLD | NEW |