OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/linked_ptr.h" | 9 #include "base/memory/linked_ptr.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 int SpdySession::trailing_ping_delay_time_ms_ = 1000; | 245 int SpdySession::trailing_ping_delay_time_ms_ = 1000; |
246 | 246 |
247 // static | 247 // static |
248 int SpdySession::hung_interval_ms_ = 10000; | 248 int SpdySession::hung_interval_ms_ = 10000; |
249 | 249 |
250 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, | 250 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, |
251 SpdySessionPool* spdy_session_pool, | 251 SpdySessionPool* spdy_session_pool, |
252 HttpServerProperties* http_server_properties, | 252 HttpServerProperties* http_server_properties, |
253 bool verify_domain_authentication, | 253 bool verify_domain_authentication, |
254 NetLog* net_log) | 254 NetLog* net_log) |
255 : ALLOW_THIS_IN_INITIALIZER_LIST( | 255 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
256 read_callback_(this, &SpdySession::OnReadComplete)), | |
257 ALLOW_THIS_IN_INITIALIZER_LIST( | |
258 write_callback_(this, &SpdySession::OnWriteComplete)), | |
259 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | |
260 host_port_proxy_pair_(host_port_proxy_pair), | 256 host_port_proxy_pair_(host_port_proxy_pair), |
261 spdy_session_pool_(spdy_session_pool), | 257 spdy_session_pool_(spdy_session_pool), |
262 http_server_properties_(http_server_properties), | 258 http_server_properties_(http_server_properties), |
263 connection_(new ClientSocketHandle), | 259 connection_(new ClientSocketHandle), |
264 read_buffer_(new IOBuffer(kReadBufferSize)), | 260 read_buffer_(new IOBuffer(kReadBufferSize)), |
265 read_pending_(false), | 261 read_pending_(false), |
266 stream_hi_water_mark_(1), // Always start at 1 for the first stream id. | 262 stream_hi_water_mark_(1), // Always start at 1 for the first stream id. |
267 write_pending_(false), | 263 write_pending_(false), |
268 delayed_write_pending_(false), | 264 delayed_write_pending_(false), |
269 is_secure_(false), | 265 is_secure_(false), |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 int error = CreateStreamImpl(*pending_create.url, | 417 int error = CreateStreamImpl(*pending_create.url, |
422 pending_create.priority, | 418 pending_create.priority, |
423 pending_create.spdy_stream, | 419 pending_create.spdy_stream, |
424 *pending_create.stream_net_log); | 420 *pending_create.stream_net_log); |
425 scoped_refptr<SpdyStream>* stream = pending_create.spdy_stream; | 421 scoped_refptr<SpdyStream>* stream = pending_create.spdy_stream; |
426 DCHECK(!ContainsKey(pending_callback_map_, stream)); | 422 DCHECK(!ContainsKey(pending_callback_map_, stream)); |
427 pending_callback_map_[stream] = | 423 pending_callback_map_[stream] = |
428 CallbackResultPair(pending_create.callback, error); | 424 CallbackResultPair(pending_create.callback, error); |
429 MessageLoop::current()->PostTask( | 425 MessageLoop::current()->PostTask( |
430 FROM_HERE, | 426 FROM_HERE, |
431 method_factory_.NewRunnableMethod( | 427 base::Bind(&SpdySession::InvokeUserStreamCreationCallback, |
432 &SpdySession::InvokeUserStreamCreationCallback, stream)); | 428 weak_factory_.GetWeakPtr(), stream)); |
433 break; | 429 break; |
434 } | 430 } |
435 } | 431 } |
436 if (no_pending_create_streams) | 432 if (no_pending_create_streams) |
437 return; // there were no streams in any queue | 433 return; // there were no streams in any queue |
438 } | 434 } |
439 } | 435 } |
440 | 436 |
441 void SpdySession::CancelPendingCreateStreams( | 437 void SpdySession::CancelPendingCreateStreams( |
442 const scoped_refptr<SpdyStream>* spdy_stream) { | 438 const scoped_refptr<SpdyStream>* spdy_stream) { |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 if (read_pending_) | 746 if (read_pending_) |
751 return OK; | 747 return OK; |
752 | 748 |
753 if (state_ == CLOSED) { | 749 if (state_ == CLOSED) { |
754 NOTREACHED(); | 750 NOTREACHED(); |
755 return ERR_UNEXPECTED; | 751 return ERR_UNEXPECTED; |
756 } | 752 } |
757 | 753 |
758 CHECK(connection_.get()); | 754 CHECK(connection_.get()); |
759 CHECK(connection_->socket()); | 755 CHECK(connection_->socket()); |
760 int bytes_read = connection_->socket()->Read(read_buffer_.get(), | 756 int bytes_read = connection_->socket()->Read( |
761 kReadBufferSize, | 757 read_buffer_.get(), |
762 &read_callback_); | 758 kReadBufferSize, |
| 759 base::Bind(&SpdySession::OnReadComplete, base::Unretained(this))); |
763 switch (bytes_read) { | 760 switch (bytes_read) { |
764 case 0: | 761 case 0: |
765 // Socket is closed! | 762 // Socket is closed! |
766 CloseSessionOnError(ERR_CONNECTION_CLOSED, true); | 763 CloseSessionOnError(ERR_CONNECTION_CLOSED, true); |
767 return ERR_CONNECTION_CLOSED; | 764 return ERR_CONNECTION_CLOSED; |
768 case net::ERR_IO_PENDING: | 765 case net::ERR_IO_PENDING: |
769 // Waiting for data. Nothing to do now. | 766 // Waiting for data. Nothing to do now. |
770 read_pending_ = true; | 767 read_pending_ = true; |
771 return ERR_IO_PENDING; | 768 return ERR_IO_PENDING; |
772 default: | 769 default: |
773 // Data was read, process it. | 770 // Data was read, process it. |
774 // Schedule the work through the message loop to avoid recursive | 771 // Schedule the work through the message loop to avoid recursive |
775 // callbacks. | 772 // callbacks. |
776 read_pending_ = true; | 773 read_pending_ = true; |
777 MessageLoop::current()->PostTask( | 774 MessageLoop::current()->PostTask( |
778 FROM_HERE, | 775 FROM_HERE, |
779 method_factory_.NewRunnableMethod( | 776 base::Bind(&SpdySession::OnReadComplete, |
780 &SpdySession::OnReadComplete, bytes_read)); | 777 weak_factory_.GetWeakPtr(), bytes_read)); |
781 break; | 778 break; |
782 } | 779 } |
783 return OK; | 780 return OK; |
784 } | 781 } |
785 | 782 |
786 void SpdySession::WriteSocketLater() { | 783 void SpdySession::WriteSocketLater() { |
787 if (delayed_write_pending_) | 784 if (delayed_write_pending_) |
788 return; | 785 return; |
789 | 786 |
790 if (state_ < CONNECTED) | 787 if (state_ < CONNECTED) |
791 return; | 788 return; |
792 | 789 |
793 delayed_write_pending_ = true; | 790 delayed_write_pending_ = true; |
794 MessageLoop::current()->PostTask( | 791 MessageLoop::current()->PostTask( |
795 FROM_HERE, | 792 FROM_HERE, |
796 method_factory_.NewRunnableMethod(&SpdySession::WriteSocket)); | 793 base::Bind(&SpdySession::WriteSocket, weak_factory_.GetWeakPtr())); |
797 } | 794 } |
798 | 795 |
799 void SpdySession::WriteSocket() { | 796 void SpdySession::WriteSocket() { |
800 // This function should only be called via WriteSocketLater. | 797 // This function should only be called via WriteSocketLater. |
801 DCHECK(delayed_write_pending_); | 798 DCHECK(delayed_write_pending_); |
802 delayed_write_pending_ = false; | 799 delayed_write_pending_ = false; |
803 | 800 |
804 // If the socket isn't connected yet, just wait; we'll get called | 801 // If the socket isn't connected yet, just wait; we'll get called |
805 // again when the socket connection completes. If the socket is | 802 // again when the socket connection completes. If the socket is |
806 // closed, just return. | 803 // closed, just return. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 in_flight_write_ = SpdyIOBuffer(buffer, size, 0, next_buffer.stream()); | 840 in_flight_write_ = SpdyIOBuffer(buffer, size, 0, next_buffer.stream()); |
844 } else { | 841 } else { |
845 size = uncompressed_frame.length() + spdy::SpdyFrame::kHeaderSize; | 842 size = uncompressed_frame.length() + spdy::SpdyFrame::kHeaderSize; |
846 in_flight_write_ = next_buffer; | 843 in_flight_write_ = next_buffer; |
847 } | 844 } |
848 } else { | 845 } else { |
849 DCHECK(in_flight_write_.buffer()->BytesRemaining()); | 846 DCHECK(in_flight_write_.buffer()->BytesRemaining()); |
850 } | 847 } |
851 | 848 |
852 write_pending_ = true; | 849 write_pending_ = true; |
853 int rv = connection_->socket()->Write(in_flight_write_.buffer(), | 850 int rv = connection_->socket()->Write( |
854 in_flight_write_.buffer()->BytesRemaining(), &write_callback_); | 851 in_flight_write_.buffer(), |
| 852 in_flight_write_.buffer()->BytesRemaining(), |
| 853 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); |
855 if (rv == net::ERR_IO_PENDING) | 854 if (rv == net::ERR_IO_PENDING) |
856 break; | 855 break; |
857 | 856 |
858 // We sent the frame successfully. | 857 // We sent the frame successfully. |
859 OnWriteComplete(rv); | 858 OnWriteComplete(rv); |
860 | 859 |
861 // TODO(mbelshe): Test this error case. Maybe we should mark the socket | 860 // TODO(mbelshe): Test this error case. Maybe we should mark the socket |
862 // as in an error state. | 861 // as in an error state. |
863 if (rv < 0) | 862 if (rv < 0) |
864 break; | 863 break; |
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 WritePingFrame(next_ping_id_); | 1588 WritePingFrame(next_ping_id_); |
1590 } | 1589 } |
1591 | 1590 |
1592 void SpdySession::PlanToSendTrailingPing() { | 1591 void SpdySession::PlanToSendTrailingPing() { |
1593 if (trailing_ping_pending_) | 1592 if (trailing_ping_pending_) |
1594 return; | 1593 return; |
1595 | 1594 |
1596 trailing_ping_pending_ = true; | 1595 trailing_ping_pending_ = true; |
1597 MessageLoop::current()->PostDelayedTask( | 1596 MessageLoop::current()->PostDelayedTask( |
1598 FROM_HERE, | 1597 FROM_HERE, |
1599 method_factory_.NewRunnableMethod(&SpdySession::SendTrailingPing), | 1598 base::Bind(&SpdySession::SendTrailingPing, weak_factory_.GetWeakPtr()), |
1600 trailing_ping_delay_time_ms_); | 1599 trailing_ping_delay_time_ms_); |
1601 } | 1600 } |
1602 | 1601 |
1603 void SpdySession::SendTrailingPing() { | 1602 void SpdySession::SendTrailingPing() { |
1604 DCHECK(trailing_ping_pending_); | 1603 DCHECK(trailing_ping_pending_); |
1605 trailing_ping_pending_ = false; | 1604 trailing_ping_pending_ = false; |
1606 WritePingFrame(next_ping_id_); | 1605 WritePingFrame(next_ping_id_); |
1607 } | 1606 } |
1608 | 1607 |
1609 void SpdySession::WritePingFrame(uint32 unique_id) { | 1608 void SpdySession::WritePingFrame(uint32 unique_id) { |
(...skipping 15 matching lines...) Expand all Loading... |
1625 } | 1624 } |
1626 } | 1625 } |
1627 | 1626 |
1628 void SpdySession::PlanToCheckPingStatus() { | 1627 void SpdySession::PlanToCheckPingStatus() { |
1629 if (check_ping_status_pending_) | 1628 if (check_ping_status_pending_) |
1630 return; | 1629 return; |
1631 | 1630 |
1632 check_ping_status_pending_ = true; | 1631 check_ping_status_pending_ = true; |
1633 MessageLoop::current()->PostDelayedTask( | 1632 MessageLoop::current()->PostDelayedTask( |
1634 FROM_HERE, | 1633 FROM_HERE, |
1635 method_factory_.NewRunnableMethod( | 1634 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), |
1636 &SpdySession::CheckPingStatus, base::TimeTicks::Now()), | 1635 base::TimeTicks::Now()), |
1637 hung_interval_ms_); | 1636 hung_interval_ms_); |
1638 } | 1637 } |
1639 | 1638 |
1640 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { | 1639 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { |
1641 // Check if we got a response back for all PINGs we had sent. | 1640 // Check if we got a response back for all PINGs we had sent. |
1642 if (pings_in_flight_ == 0) { | 1641 if (pings_in_flight_ == 0) { |
1643 check_ping_status_pending_ = false; | 1642 check_ping_status_pending_ = false; |
1644 return; | 1643 return; |
1645 } | 1644 } |
1646 | 1645 |
(...skipping 10 matching lines...) Expand all Loading... |
1657 // Track all failed PING messages in a separate bucket. | 1656 // Track all failed PING messages in a separate bucket. |
1658 const base::TimeDelta kFailedPing = | 1657 const base::TimeDelta kFailedPing = |
1659 base::TimeDelta::FromInternalValue(INT_MAX); | 1658 base::TimeDelta::FromInternalValue(INT_MAX); |
1660 RecordPingRTTHistogram(kFailedPing); | 1659 RecordPingRTTHistogram(kFailedPing); |
1661 return; | 1660 return; |
1662 } | 1661 } |
1663 | 1662 |
1664 // Check the status of connection after a delay. | 1663 // Check the status of connection after a delay. |
1665 MessageLoop::current()->PostDelayedTask( | 1664 MessageLoop::current()->PostDelayedTask( |
1666 FROM_HERE, | 1665 FROM_HERE, |
1667 method_factory_.NewRunnableMethod(&SpdySession::CheckPingStatus, now), | 1666 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), |
| 1667 now), |
1668 delay.InMilliseconds()); | 1668 delay.InMilliseconds()); |
1669 } | 1669 } |
1670 | 1670 |
1671 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { | 1671 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { |
1672 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); | 1672 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); |
1673 } | 1673 } |
1674 | 1674 |
1675 void SpdySession::RecordHistograms() { | 1675 void SpdySession::RecordHistograms() { |
1676 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", | 1676 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", |
1677 streams_initiated_count_, | 1677 streams_initiated_count_, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1754 if (it == pending_callback_map_.end()) | 1754 if (it == pending_callback_map_.end()) |
1755 return; | 1755 return; |
1756 | 1756 |
1757 OldCompletionCallback* callback = it->second.callback; | 1757 OldCompletionCallback* callback = it->second.callback; |
1758 int result = it->second.result; | 1758 int result = it->second.result; |
1759 pending_callback_map_.erase(it); | 1759 pending_callback_map_.erase(it); |
1760 callback->Run(result); | 1760 callback->Run(result); |
1761 } | 1761 } |
1762 | 1762 |
1763 } // namespace net | 1763 } // namespace net |
OLD | NEW |