| 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 |