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 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { | 139 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { |
140 #if defined(OS_LINUX) || defined(OS_ANDROID) | 140 #if defined(OS_LINUX) || defined(OS_ANDROID) |
141 base::PostTaskAndReplyWithResult( | 141 base::PostTaskAndReplyWithResult( |
142 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), | 142 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), |
143 FROM_HERE, | 143 FROM_HERE, |
144 base::Bind(SystemSupportsTCPFastOpen), | 144 base::Bind(SystemSupportsTCPFastOpen), |
145 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); | 145 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); |
146 #endif | 146 #endif |
147 } | 147 } |
148 | 148 |
149 TCPSocketPosix::TCPSocketPosix(NetLog* net_log, const NetLog::Source& source) | 149 TCPSocketPosix::TCPSocketPosix( |
150 : use_tcp_fastopen_(false), | 150 scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher, |
151 NetLog* net_log, | |
152 const NetLog::Source& source) | |
153 : socket_performance_watcher_(std::move(socket_performance_watcher)), | |
154 use_tcp_fastopen_(false), | |
151 tcp_fastopen_write_attempted_(false), | 155 tcp_fastopen_write_attempted_(false), |
152 tcp_fastopen_connected_(false), | 156 tcp_fastopen_connected_(false), |
153 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), | 157 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), |
154 logging_multiple_connect_attempts_(false), | 158 logging_multiple_connect_attempts_(false), |
155 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 159 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
156 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 160 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
157 source.ToEventParametersCallback()); | 161 source.ToEventParametersCallback()); |
158 } | 162 } |
159 | 163 |
160 TCPSocketPosix::~TCPSocketPosix() { | 164 TCPSocketPosix::~TCPSocketPosix() { |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 IPEndPoint* address) { | 521 IPEndPoint* address) { |
518 DCHECK(accept_socket_); | 522 DCHECK(accept_socket_); |
519 | 523 |
520 SockaddrStorage storage; | 524 SockaddrStorage storage; |
521 if (accept_socket_->GetPeerAddress(&storage) != OK || | 525 if (accept_socket_->GetPeerAddress(&storage) != OK || |
522 !address->FromSockAddr(storage.addr, storage.addr_len)) { | 526 !address->FromSockAddr(storage.addr, storage.addr_len)) { |
523 accept_socket_.reset(); | 527 accept_socket_.reset(); |
524 return ERR_ADDRESS_INVALID; | 528 return ERR_ADDRESS_INVALID; |
525 } | 529 } |
526 | 530 |
527 tcp_socket->reset(new TCPSocketPosix(net_log_.net_log(), net_log_.source())); | 531 tcp_socket->reset( |
532 new TCPSocketPosix(nullptr, net_log_.net_log(), net_log_.source())); | |
528 (*tcp_socket)->socket_.reset(accept_socket_.release()); | 533 (*tcp_socket)->socket_.reset(accept_socket_.release()); |
529 return OK; | 534 return OK; |
530 } | 535 } |
531 | 536 |
532 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, | 537 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, |
533 int rv) const { | 538 int rv) const { |
534 DCHECK_NE(ERR_IO_PENDING, rv); | 539 DCHECK_NE(ERR_IO_PENDING, rv); |
540 NotifySocketPerformanceWatcher(); | |
535 callback.Run(HandleConnectCompleted(rv)); | 541 callback.Run(HandleConnectCompleted(rv)); |
536 } | 542 } |
537 | 543 |
538 int TCPSocketPosix::HandleConnectCompleted(int rv) const { | 544 int TCPSocketPosix::HandleConnectCompleted(int rv) const { |
539 // Log the end of this attempt (and any OS error it threw). | 545 // Log the end of this attempt (and any OS error it threw). |
540 if (rv != OK) { | 546 if (rv != OK) { |
541 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | 547 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, |
542 NetLog::IntCallback("os_error", errno)); | 548 NetLog::IntCallback("os_error", errno)); |
543 } else { | 549 } else { |
544 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); | 550 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 | 584 |
579 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, | 585 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, |
580 CreateNetLogSourceAddressCallback(storage.addr, | 586 CreateNetLogSourceAddressCallback(storage.addr, |
581 storage.addr_len)); | 587 storage.addr_len)); |
582 } | 588 } |
583 | 589 |
584 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf, | 590 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf, |
585 const CompletionCallback& callback, | 591 const CompletionCallback& callback, |
586 int rv) { | 592 int rv) { |
587 DCHECK_NE(ERR_IO_PENDING, rv); | 593 DCHECK_NE(ERR_IO_PENDING, rv); |
594 NotifySocketPerformanceWatcher(); | |
588 callback.Run(HandleReadCompleted(buf.get(), rv)); | 595 callback.Run(HandleReadCompleted(buf.get(), rv)); |
589 } | 596 } |
590 | 597 |
591 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) { | 598 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) { |
592 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 599 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
593 // A TCP FastOpen connect-with-write was attempted. This read was a | 600 // A TCP FastOpen connect-with-write was attempted. This read was a |
594 // subsequent read, which either succeeded or failed. If the read | 601 // subsequent read, which either succeeded or failed. If the read |
595 // succeeded, the socket is considered connected via TCP FastOpen. | 602 // succeeded, the socket is considered connected via TCP FastOpen. |
596 // If the read failed, TCP FastOpen is (conservatively) turned off for all | 603 // If the read failed, TCP FastOpen is (conservatively) turned off for all |
597 // subsequent connections. TCP FastOpen status is recorded in both cases. | 604 // subsequent connections. TCP FastOpen status is recorded in both cases. |
(...skipping 17 matching lines...) Expand all Loading... | |
615 buf->data()); | 622 buf->data()); |
616 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); | 623 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); |
617 | 624 |
618 return rv; | 625 return rv; |
619 } | 626 } |
620 | 627 |
621 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, | 628 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, |
622 const CompletionCallback& callback, | 629 const CompletionCallback& callback, |
623 int rv) { | 630 int rv) { |
624 DCHECK_NE(ERR_IO_PENDING, rv); | 631 DCHECK_NE(ERR_IO_PENDING, rv); |
632 NotifySocketPerformanceWatcher(); | |
625 callback.Run(HandleWriteCompleted(buf.get(), rv)); | 633 callback.Run(HandleWriteCompleted(buf.get(), rv)); |
626 } | 634 } |
627 | 635 |
628 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) { | 636 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) { |
629 if (rv < 0) { | 637 if (rv < 0) { |
630 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 638 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
631 // TCP FastOpen connect-with-write was attempted, and the write failed | 639 // TCP FastOpen connect-with-write was attempted, and the write failed |
632 // for unknown reasons. Record status and (conservatively) turn off | 640 // for unknown reasons. Record status and (conservatively) turn off |
633 // TCP FastOpen for all subsequent connections. | 641 // TCP FastOpen for all subsequent connections. |
634 // TODO (jri): This currently results in conservative behavior, where TCP | 642 // TODO (jri): This currently results in conservative behavior, where TCP |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 // turning off TCP FastOpen on more specific errors. | 710 // turning off TCP FastOpen on more specific errors. |
703 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; | 711 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; |
704 g_tcp_fastopen_has_failed = true; | 712 g_tcp_fastopen_has_failed = true; |
705 return rv; | 713 return rv; |
706 } | 714 } |
707 | 715 |
708 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; | 716 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; |
709 return socket_->WaitForWrite(buf, buf_len, callback); | 717 return socket_->WaitForWrite(buf, buf_len, callback); |
710 } | 718 } |
711 | 719 |
720 void TCPSocketPosix::NotifySocketPerformanceWatcher() const { | |
721 #if defined(TCP_INFO) | |
722 if (!socket_performance_watcher_) | |
723 return; | |
724 | |
725 tcp_info info; | |
726 if (!GetTcpInfo(socket_->socket_fd(), &info)) | |
Ryan Sleevi
2016/02/23 21:19:10
And you're sure the syscall overhead here is not g
mmenke
2016/02/23 21:31:31
Also, calling this on every read or write seems un
| |
727 return; | |
728 | |
729 if (info.tcpi_rtt > 0) { | |
730 // Zero RTT value indicates that tcp_info struct was not properly populated. | |
731 socket_performance_watcher_->OnUpdatedRTTAvailable( | |
732 base::TimeDelta::FromMicroseconds(info.tcpi_rtt)); | |
733 } | |
734 #endif // defined(TCP_INFO) | |
735 } | |
736 | |
712 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { | 737 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { |
713 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || | 738 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || |
714 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); | 739 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); |
715 | 740 |
716 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 741 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
717 // TCP FastOpen connect-with-write was attempted, and failed. | 742 // TCP FastOpen connect-with-write was attempted, and failed. |
718 tcp_fastopen_status_ = | 743 tcp_fastopen_status_ = |
719 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? | 744 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? |
720 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : | 745 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : |
721 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); | 746 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
763 if (info.tcpi_rtt > 0) { | 788 if (info.tcpi_rtt > 0) { |
764 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); | 789 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); |
765 return true; | 790 return true; |
766 } | 791 } |
767 } | 792 } |
768 #endif // defined(TCP_INFO) | 793 #endif // defined(TCP_INFO) |
769 return false; | 794 return false; |
770 } | 795 } |
771 | 796 |
772 } // namespace net | 797 } // namespace net |
OLD | NEW |