| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 void SpdyStreamRequest::Reset() { | 532 void SpdyStreamRequest::Reset() { |
| 533 type_ = SPDY_BIDIRECTIONAL_STREAM; | 533 type_ = SPDY_BIDIRECTIONAL_STREAM; |
| 534 session_.reset(); | 534 session_.reset(); |
| 535 stream_.reset(); | 535 stream_.reset(); |
| 536 url_ = GURL(); | 536 url_ = GURL(); |
| 537 priority_ = MINIMUM_PRIORITY; | 537 priority_ = MINIMUM_PRIORITY; |
| 538 net_log_ = NetLogWithSource(); | 538 net_log_ = NetLogWithSource(); |
| 539 callback_.Reset(); | 539 callback_.Reset(); |
| 540 } | 540 } |
| 541 | 541 |
| 542 SpdySession::ActiveStreamInfo::ActiveStreamInfo() | |
| 543 : stream(NULL), waiting_for_reply_headers_frame(false) {} | |
| 544 | |
| 545 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) | |
| 546 : stream(stream), | |
| 547 waiting_for_reply_headers_frame(stream->type() != SPDY_PUSH_STREAM) {} | |
| 548 | |
| 549 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {} | |
| 550 | |
| 551 SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer( | 542 SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer( |
| 552 SpdySession* spdy_session) | 543 SpdySession* spdy_session) |
| 553 : spdy_session_(spdy_session) {} | 544 : spdy_session_(spdy_session) {} |
| 554 SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() { | 545 SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() { |
| 555 } | 546 } |
| 556 | 547 |
| 557 size_t SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) { | 548 size_t SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) { |
| 558 const_iterator it = find(url); | 549 const_iterator it = find(url); |
| 559 if (it != end()) { | 550 if (it != end()) { |
| 560 streams_.erase(it); | 551 streams_.erase(it); |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream); | 979 EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream); |
| 989 } | 980 } |
| 990 | 981 |
| 991 std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders( | 982 std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders( |
| 992 SpdyStreamId stream_id, | 983 SpdyStreamId stream_id, |
| 993 RequestPriority priority, | 984 RequestPriority priority, |
| 994 SpdyControlFlags flags, | 985 SpdyControlFlags flags, |
| 995 SpdyHeaderBlock block) { | 986 SpdyHeaderBlock block) { |
| 996 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 987 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 997 CHECK(it != active_streams_.end()); | 988 CHECK(it != active_streams_.end()); |
| 998 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 989 CHECK_EQ(it->second->stream_id(), stream_id); |
| 999 | 990 |
| 1000 SendPrefacePingIfNoneInFlight(); | 991 SendPrefacePingIfNoneInFlight(); |
| 1001 | 992 |
| 1002 DCHECK(buffered_spdy_framer_.get()); | 993 DCHECK(buffered_spdy_framer_.get()); |
| 1003 SpdyPriority spdy_priority = ConvertRequestPriorityToSpdyPriority(priority); | 994 SpdyPriority spdy_priority = ConvertRequestPriorityToSpdyPriority(priority); |
| 1004 | 995 |
| 1005 std::unique_ptr<SpdySerializedFrame> syn_frame; | 996 std::unique_ptr<SpdySerializedFrame> syn_frame; |
| 1006 bool has_priority = true; | 997 bool has_priority = true; |
| 1007 int weight = Spdy3PriorityToHttp2Weight(spdy_priority); | 998 int weight = Spdy3PriorityToHttp2Weight(spdy_priority); |
| 1008 SpdyStreamId dependent_stream_id = 0; | 999 SpdyStreamId dependent_stream_id = 0; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1037 SpdyStreamId stream_id, | 1028 SpdyStreamId stream_id, |
| 1038 IOBuffer* data, | 1029 IOBuffer* data, |
| 1039 int len, | 1030 int len, |
| 1040 SpdyDataFlags flags) { | 1031 SpdyDataFlags flags) { |
| 1041 if (availability_state_ == STATE_DRAINING) { | 1032 if (availability_state_ == STATE_DRAINING) { |
| 1042 return std::unique_ptr<SpdyBuffer>(); | 1033 return std::unique_ptr<SpdyBuffer>(); |
| 1043 } | 1034 } |
| 1044 | 1035 |
| 1045 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 1036 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 1046 CHECK(it != active_streams_.end()); | 1037 CHECK(it != active_streams_.end()); |
| 1047 SpdyStream* stream = it->second.stream; | 1038 SpdyStream* stream = it->second; |
| 1048 CHECK_EQ(stream->stream_id(), stream_id); | 1039 CHECK_EQ(stream->stream_id(), stream_id); |
| 1049 | 1040 |
| 1050 if (len < 0) { | 1041 if (len < 0) { |
| 1051 NOTREACHED(); | 1042 NOTREACHED(); |
| 1052 return std::unique_ptr<SpdyBuffer>(); | 1043 return std::unique_ptr<SpdyBuffer>(); |
| 1053 } | 1044 } |
| 1054 | 1045 |
| 1055 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); | 1046 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); |
| 1056 | 1047 |
| 1057 bool send_stalled_by_stream = (stream->send_window_size() <= 0); | 1048 bool send_stalled_by_stream = (stream->send_window_size() <= 0); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 // Just report that we're idle since the session could be doing | 1183 // Just report that we're idle since the session could be doing |
| 1193 // many things concurrently. | 1184 // many things concurrently. |
| 1194 return LOAD_STATE_IDLE; | 1185 return LOAD_STATE_IDLE; |
| 1195 } | 1186 } |
| 1196 | 1187 |
| 1197 void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it, | 1188 void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it, |
| 1198 int status) { | 1189 int status) { |
| 1199 // TODO(mbelshe): We should send a RST_STREAM control frame here | 1190 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 1200 // so that the server can cancel a large send. | 1191 // so that the server can cancel a large send. |
| 1201 | 1192 |
| 1202 std::unique_ptr<SpdyStream> owned_stream(it->second.stream); | 1193 std::unique_ptr<SpdyStream> owned_stream(it->second); |
| 1203 active_streams_.erase(it); | 1194 active_streams_.erase(it); |
| 1204 priority_dependency_state_.OnStreamDestruction(owned_stream->stream_id()); | 1195 priority_dependency_state_.OnStreamDestruction(owned_stream->stream_id()); |
| 1205 | 1196 |
| 1206 // TODO(akalin): When SpdyStream was ref-counted (and | 1197 // TODO(akalin): When SpdyStream was ref-counted (and |
| 1207 // |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this | 1198 // |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this |
| 1208 // was only done when status was not OK. This meant that pushed | 1199 // was only done when status was not OK. This meant that pushed |
| 1209 // streams can still be claimed after they're closed. This is | 1200 // streams can still be claimed after they're closed. This is |
| 1210 // probably something that we still want to support, although server | 1201 // probably something that we still want to support, although server |
| 1211 // push is hardly used. Write tests for this and fix this. (See | 1202 // push is hardly used. Write tests for this and fix this. (See |
| 1212 // http://crbug.com/261712 .) | 1203 // http://crbug.com/261712 .) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1234 created_streams_.erase(it); | 1225 created_streams_.erase(it); |
| 1235 DeleteStream(std::move(owned_stream), status); | 1226 DeleteStream(std::move(owned_stream), status); |
| 1236 } | 1227 } |
| 1237 | 1228 |
| 1238 void SpdySession::ResetStreamIterator(ActiveStreamMap::iterator it, | 1229 void SpdySession::ResetStreamIterator(ActiveStreamMap::iterator it, |
| 1239 SpdyRstStreamStatus status, | 1230 SpdyRstStreamStatus status, |
| 1240 const std::string& description) { | 1231 const std::string& description) { |
| 1241 // Send the RST_STREAM frame first as CloseActiveStreamIterator() | 1232 // Send the RST_STREAM frame first as CloseActiveStreamIterator() |
| 1242 // may close us. | 1233 // may close us. |
| 1243 SpdyStreamId stream_id = it->first; | 1234 SpdyStreamId stream_id = it->first; |
| 1244 RequestPriority priority = it->second.stream->priority(); | 1235 RequestPriority priority = it->second->priority(); |
| 1245 EnqueueResetStreamFrame(stream_id, priority, status, description); | 1236 EnqueueResetStreamFrame(stream_id, priority, status, description); |
| 1246 | 1237 |
| 1247 // Removes any pending writes for the stream except for possibly an | 1238 // Removes any pending writes for the stream except for possibly an |
| 1248 // in-flight one. | 1239 // in-flight one. |
| 1249 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); | 1240 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); |
| 1250 } | 1241 } |
| 1251 | 1242 |
| 1252 void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id, | 1243 void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id, |
| 1253 RequestPriority priority, | 1244 RequestPriority priority, |
| 1254 SpdyRstStreamStatus status, | 1245 SpdyRstStreamStatus status, |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 stream->LogStreamError(status, description); | 1674 stream->LogStreamError(status, description); |
| 1684 // We don't increment the streams abandoned counter here. If the | 1675 // We don't increment the streams abandoned counter here. If the |
| 1685 // stream isn't active (i.e., it hasn't written anything to the wire | 1676 // stream isn't active (i.e., it hasn't written anything to the wire |
| 1686 // yet) then it's as if it never existed. If it is active, then | 1677 // yet) then it's as if it never existed. If it is active, then |
| 1687 // LogAbandonedActiveStream() will increment the counters. | 1678 // LogAbandonedActiveStream() will increment the counters. |
| 1688 } | 1679 } |
| 1689 | 1680 |
| 1690 void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it, | 1681 void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it, |
| 1691 Error status) { | 1682 Error status) { |
| 1692 DCHECK_GT(it->first, 0u); | 1683 DCHECK_GT(it->first, 0u); |
| 1693 LogAbandonedStream(it->second.stream, status); | 1684 LogAbandonedStream(it->second, status); |
| 1694 ++streams_abandoned_count_; | 1685 ++streams_abandoned_count_; |
| 1695 } | 1686 } |
| 1696 | 1687 |
| 1697 SpdyStreamId SpdySession::GetNewStreamId() { | 1688 SpdyStreamId SpdySession::GetNewStreamId() { |
| 1698 CHECK_LE(stream_hi_water_mark_, kLastStreamId); | 1689 CHECK_LE(stream_hi_water_mark_, kLastStreamId); |
| 1699 SpdyStreamId id = stream_hi_water_mark_; | 1690 SpdyStreamId id = stream_hi_water_mark_; |
| 1700 stream_hi_water_mark_ += 2; | 1691 stream_hi_water_mark_ += 2; |
| 1701 return id; | 1692 return id; |
| 1702 } | 1693 } |
| 1703 | 1694 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 stream->set_stream_id(GetNewStreamId()); | 1832 stream->set_stream_id(GetNewStreamId()); |
| 1842 std::unique_ptr<SpdyStream> owned_stream(stream); | 1833 std::unique_ptr<SpdyStream> owned_stream(stream); |
| 1843 created_streams_.erase(stream); | 1834 created_streams_.erase(stream); |
| 1844 return owned_stream; | 1835 return owned_stream; |
| 1845 } | 1836 } |
| 1846 | 1837 |
| 1847 void SpdySession::InsertActivatedStream(std::unique_ptr<SpdyStream> stream) { | 1838 void SpdySession::InsertActivatedStream(std::unique_ptr<SpdyStream> stream) { |
| 1848 SpdyStreamId stream_id = stream->stream_id(); | 1839 SpdyStreamId stream_id = stream->stream_id(); |
| 1849 CHECK_NE(stream_id, 0u); | 1840 CHECK_NE(stream_id, 0u); |
| 1850 std::pair<ActiveStreamMap::iterator, bool> result = | 1841 std::pair<ActiveStreamMap::iterator, bool> result = |
| 1851 active_streams_.insert( | 1842 active_streams_.insert(std::make_pair(stream_id, stream.get())); |
| 1852 std::make_pair(stream_id, ActiveStreamInfo(stream.get()))); | |
| 1853 CHECK(result.second); | 1843 CHECK(result.second); |
| 1854 ignore_result(stream.release()); | 1844 ignore_result(stream.release()); |
| 1855 } | 1845 } |
| 1856 | 1846 |
| 1857 void SpdySession::DeleteStream(std::unique_ptr<SpdyStream> stream, int status) { | 1847 void SpdySession::DeleteStream(std::unique_ptr<SpdyStream> stream, int status) { |
| 1858 if (in_flight_write_stream_.get() == stream.get()) { | 1848 if (in_flight_write_stream_.get() == stream.get()) { |
| 1859 // If we're deleting the stream for the in-flight write, we still | 1849 // If we're deleting the stream for the in-flight write, we still |
| 1860 // need to let the write complete, so we clear | 1850 // need to let the write complete, so we clear |
| 1861 // |in_flight_write_stream_| and let the write finish on its own | 1851 // |in_flight_write_stream_| and let the write finish on its own |
| 1862 // without notifying |in_flight_write_stream_|. | 1852 // without notifying |in_flight_write_stream_|. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1889 unclaimed_pushed_streams_.erase(unclaimed_it); | 1879 unclaimed_pushed_streams_.erase(unclaimed_it); |
| 1890 | 1880 |
| 1891 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); | 1881 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); |
| 1892 if (active_it == active_streams_.end()) { | 1882 if (active_it == active_streams_.end()) { |
| 1893 NOTREACHED(); | 1883 NOTREACHED(); |
| 1894 return base::WeakPtr<SpdyStream>(); | 1884 return base::WeakPtr<SpdyStream>(); |
| 1895 } | 1885 } |
| 1896 | 1886 |
| 1897 net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ADOPTED_PUSH_STREAM, | 1887 net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ADOPTED_PUSH_STREAM, |
| 1898 base::Bind(&NetLogSpdyAdoptedPushStreamCallback, | 1888 base::Bind(&NetLogSpdyAdoptedPushStreamCallback, |
| 1899 active_it->second.stream->stream_id(), &url)); | 1889 active_it->second->stream_id(), &url)); |
| 1900 return active_it->second.stream->GetWeakPtr(); | 1890 return active_it->second->GetWeakPtr(); |
| 1901 } | 1891 } |
| 1902 | 1892 |
| 1903 url::SchemeHostPort SpdySession::GetServer() { | 1893 url::SchemeHostPort SpdySession::GetServer() { |
| 1904 return url::SchemeHostPort(is_secure_ ? "https" : "http", | 1894 return url::SchemeHostPort(is_secure_ ? "https" : "http", |
| 1905 host_port_pair().host(), host_port_pair().port()); | 1895 host_port_pair().host(), host_port_pair().port()); |
| 1906 } | 1896 } |
| 1907 | 1897 |
| 1908 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info) const { | 1898 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info) const { |
| 1909 return connection_->socket()->GetSSLInfo(ssl_info); | 1899 return connection_->socket()->GetSSLInfo(ssl_info); |
| 1910 } | 1900 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 size_t length, | 1950 size_t length, |
| 1961 bool fin) { | 1951 bool fin) { |
| 1962 CHECK(in_io_loop_); | 1952 CHECK(in_io_loop_); |
| 1963 | 1953 |
| 1964 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 1954 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 1965 | 1955 |
| 1966 // By the time data comes in, the stream may already be inactive. | 1956 // By the time data comes in, the stream may already be inactive. |
| 1967 if (it == active_streams_.end()) | 1957 if (it == active_streams_.end()) |
| 1968 return; | 1958 return; |
| 1969 | 1959 |
| 1970 SpdyStream* stream = it->second.stream; | 1960 SpdyStream* stream = it->second; |
| 1971 CHECK_EQ(stream->stream_id(), stream_id); | 1961 CHECK_EQ(stream->stream_id(), stream_id); |
| 1972 | 1962 |
| 1973 DCHECK(buffered_spdy_framer_); | 1963 DCHECK(buffered_spdy_framer_); |
| 1974 size_t header_len = buffered_spdy_framer_->GetDataFrameMinimumSize(); | 1964 size_t header_len = buffered_spdy_framer_->GetDataFrameMinimumSize(); |
| 1975 stream->AddRawReceivedBytes(header_len); | 1965 stream->AddRawReceivedBytes(header_len); |
| 1976 } | 1966 } |
| 1977 | 1967 |
| 1978 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, | 1968 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, |
| 1979 const char* data, | 1969 const char* data, |
| 1980 size_t len) { | 1970 size_t len) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2003 } else { | 1993 } else { |
| 2004 DCHECK_EQ(len, 0u); | 1994 DCHECK_EQ(len, 0u); |
| 2005 } | 1995 } |
| 2006 | 1996 |
| 2007 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 1997 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2008 | 1998 |
| 2009 // By the time data comes in, the stream may already be inactive. | 1999 // By the time data comes in, the stream may already be inactive. |
| 2010 if (it == active_streams_.end()) | 2000 if (it == active_streams_.end()) |
| 2011 return; | 2001 return; |
| 2012 | 2002 |
| 2013 SpdyStream* stream = it->second.stream; | 2003 SpdyStream* stream = it->second; |
| 2014 CHECK_EQ(stream->stream_id(), stream_id); | 2004 CHECK_EQ(stream->stream_id(), stream_id); |
| 2015 | 2005 |
| 2016 stream->AddRawReceivedBytes(len); | 2006 stream->AddRawReceivedBytes(len); |
| 2017 | |
| 2018 if (it->second.waiting_for_reply_headers_frame) { | |
| 2019 const std::string& error = "DATA received before HEADERS."; | |
| 2020 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | |
| 2021 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | |
| 2022 return; | |
| 2023 } | |
| 2024 | |
| 2025 stream->OnDataReceived(std::move(buffer)); | 2007 stream->OnDataReceived(std::move(buffer)); |
| 2026 } | 2008 } |
| 2027 | 2009 |
| 2028 void SpdySession::OnStreamEnd(SpdyStreamId stream_id) { | 2010 void SpdySession::OnStreamEnd(SpdyStreamId stream_id) { |
| 2029 CHECK(in_io_loop_); | 2011 CHECK(in_io_loop_); |
| 2030 if (net_log().IsCapturing()) { | 2012 if (net_log().IsCapturing()) { |
| 2031 net_log().AddEvent(NetLogEventType::HTTP2_SESSION_RECV_DATA, | 2013 net_log().AddEvent(NetLogEventType::HTTP2_SESSION_RECV_DATA, |
| 2032 base::Bind(&NetLogSpdyDataCallback, stream_id, 0, true)); | 2014 base::Bind(&NetLogSpdyDataCallback, stream_id, 0, true)); |
| 2033 } | 2015 } |
| 2034 | 2016 |
| 2035 // Build the buffer as early as possible so that we go through the | 2017 // Build the buffer as early as possible so that we go through the |
| 2036 // session flow control checks and update | 2018 // session flow control checks and update |
| 2037 // |unacked_recv_window_bytes_| properly even when the stream is | 2019 // |unacked_recv_window_bytes_| properly even when the stream is |
| 2038 // inactive (since the other side has still reduced its session send | 2020 // inactive (since the other side has still reduced its session send |
| 2039 // window). | 2021 // window). |
| 2040 std::unique_ptr<SpdyBuffer> buffer; | 2022 std::unique_ptr<SpdyBuffer> buffer; |
| 2041 | 2023 |
| 2042 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2024 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2043 | 2025 |
| 2044 // By the time data comes in, the stream may already be inactive. | 2026 // By the time data comes in, the stream may already be inactive. |
| 2045 if (it == active_streams_.end()) | 2027 if (it == active_streams_.end()) |
| 2046 return; | 2028 return; |
| 2047 | 2029 |
| 2048 SpdyStream* stream = it->second.stream; | 2030 SpdyStream* stream = it->second; |
| 2049 CHECK_EQ(stream->stream_id(), stream_id); | 2031 CHECK_EQ(stream->stream_id(), stream_id); |
| 2050 | 2032 |
| 2051 if (it->second.waiting_for_reply_headers_frame) { | |
| 2052 const std::string& error = "DATA received before HEADERS."; | |
| 2053 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | |
| 2054 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | |
| 2055 return; | |
| 2056 } | |
| 2057 | |
| 2058 stream->OnDataReceived(std::move(buffer)); | 2033 stream->OnDataReceived(std::move(buffer)); |
| 2059 } | 2034 } |
| 2060 | 2035 |
| 2061 void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) { | 2036 void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) { |
| 2062 CHECK(in_io_loop_); | 2037 CHECK(in_io_loop_); |
| 2063 | 2038 |
| 2064 // Decrease window size because padding bytes are received. | 2039 // Decrease window size because padding bytes are received. |
| 2065 // Increase window size because padding bytes are consumed (by discarding). | 2040 // Increase window size because padding bytes are consumed (by discarding). |
| 2066 // Net result: |session_unacked_recv_window_bytes_| increases by |len|, | 2041 // Net result: |session_unacked_recv_window_bytes_| increases by |len|, |
| 2067 // |session_recv_window_size_| does not change. | 2042 // |session_recv_window_size_| does not change. |
| 2068 DecreaseRecvWindowSize(static_cast<int32_t>(len)); | 2043 DecreaseRecvWindowSize(static_cast<int32_t>(len)); |
| 2069 IncreaseRecvWindowSize(static_cast<int32_t>(len)); | 2044 IncreaseRecvWindowSize(static_cast<int32_t>(len)); |
| 2070 | 2045 |
| 2071 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2046 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2072 if (it == active_streams_.end()) | 2047 if (it == active_streams_.end()) |
| 2073 return; | 2048 return; |
| 2074 it->second.stream->OnPaddingConsumed(len); | 2049 it->second->OnPaddingConsumed(len); |
| 2075 } | 2050 } |
| 2076 | 2051 |
| 2077 void SpdySession::OnSettings() { | 2052 void SpdySession::OnSettings() { |
| 2078 CHECK(in_io_loop_); | 2053 CHECK(in_io_loop_); |
| 2079 | 2054 |
| 2080 if (net_log_.IsCapturing()) { | 2055 if (net_log_.IsCapturing()) { |
| 2081 net_log_.AddEvent( | 2056 net_log_.AddEvent( |
| 2082 NetLogEventType::HTTP2_SESSION_RECV_SETTINGS, | 2057 NetLogEventType::HTTP2_SESSION_RECV_SETTINGS, |
| 2083 base::Bind(&NetLogSpdySettingsCallback, host_port_pair())); | 2058 base::Bind(&NetLogSpdySettingsCallback, host_port_pair())); |
| 2084 } | 2059 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2123 } | 2098 } |
| 2124 } | 2099 } |
| 2125 | 2100 |
| 2126 void SpdySession::OnReceiveCompressedFrame( | 2101 void SpdySession::OnReceiveCompressedFrame( |
| 2127 SpdyStreamId stream_id, | 2102 SpdyStreamId stream_id, |
| 2128 SpdyFrameType type, | 2103 SpdyFrameType type, |
| 2129 size_t frame_len) { | 2104 size_t frame_len) { |
| 2130 last_compressed_frame_len_ = frame_len; | 2105 last_compressed_frame_len_ = frame_len; |
| 2131 } | 2106 } |
| 2132 | 2107 |
| 2133 int SpdySession::OnInitialResponseHeadersReceived( | |
| 2134 const SpdyHeaderBlock& response_headers, | |
| 2135 base::Time response_time, | |
| 2136 base::TimeTicks recv_first_byte_time, | |
| 2137 SpdyStream* stream) { | |
| 2138 CHECK(in_io_loop_); | |
| 2139 SpdyStreamId stream_id = stream->stream_id(); | |
| 2140 | |
| 2141 if (stream->type() == SPDY_PUSH_STREAM) { | |
| 2142 DCHECK(stream->IsReservedRemote()); | |
| 2143 if (max_concurrent_pushed_streams_ && | |
| 2144 num_active_pushed_streams_ >= max_concurrent_pushed_streams_) { | |
| 2145 ResetStream(stream_id, | |
| 2146 RST_STREAM_REFUSED_STREAM, | |
| 2147 "Stream concurrency limit reached."); | |
| 2148 return STATUS_CODE_REFUSED_STREAM; | |
| 2149 } | |
| 2150 } | |
| 2151 | |
| 2152 if (stream->type() == SPDY_PUSH_STREAM) { | |
| 2153 // Will be balanced in DeleteStream. | |
| 2154 num_active_pushed_streams_++; | |
| 2155 } | |
| 2156 | |
| 2157 // May invalidate |stream|. | |
| 2158 int rv = stream->OnInitialResponseHeadersReceived( | |
| 2159 response_headers, response_time, recv_first_byte_time); | |
| 2160 if (rv < 0) { | |
| 2161 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 2162 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | |
| 2163 } | |
| 2164 | |
| 2165 return rv; | |
| 2166 } | |
| 2167 | |
| 2168 void SpdySession::DeleteExpiredPushedStreams() { | 2108 void SpdySession::DeleteExpiredPushedStreams() { |
| 2169 if (unclaimed_pushed_streams_.empty()) | 2109 if (unclaimed_pushed_streams_.empty()) |
| 2170 return; | 2110 return; |
| 2171 | 2111 |
| 2172 // Check that adequate time has elapsed since the last sweep. | 2112 // Check that adequate time has elapsed since the last sweep. |
| 2173 if (time_func_() < next_unclaimed_push_stream_sweep_time_) | 2113 if (time_func_() < next_unclaimed_push_stream_sweep_time_) |
| 2174 return; | 2114 return; |
| 2175 | 2115 |
| 2176 // Gather old streams to delete. | 2116 // Gather old streams to delete. |
| 2177 base::TimeTicks minimum_freshness = time_func_() - | 2117 base::TimeTicks minimum_freshness = time_func_() - |
| 2178 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 2118 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 2179 std::vector<SpdyStreamId> streams_to_close; | 2119 std::vector<SpdyStreamId> streams_to_close; |
| 2180 for (UnclaimedPushedStreamContainer::const_iterator it = | 2120 for (UnclaimedPushedStreamContainer::const_iterator it = |
| 2181 unclaimed_pushed_streams_.begin(); | 2121 unclaimed_pushed_streams_.begin(); |
| 2182 it != unclaimed_pushed_streams_.end(); ++it) { | 2122 it != unclaimed_pushed_streams_.end(); ++it) { |
| 2183 if (minimum_freshness > it->second.creation_time) | 2123 if (minimum_freshness > it->second.creation_time) |
| 2184 streams_to_close.push_back(it->second.stream_id); | 2124 streams_to_close.push_back(it->second.stream_id); |
| 2185 } | 2125 } |
| 2186 | 2126 |
| 2187 for (std::vector<SpdyStreamId>::const_iterator to_close_it = | 2127 for (std::vector<SpdyStreamId>::const_iterator to_close_it = |
| 2188 streams_to_close.begin(); | 2128 streams_to_close.begin(); |
| 2189 to_close_it != streams_to_close.end(); ++to_close_it) { | 2129 to_close_it != streams_to_close.end(); ++to_close_it) { |
| 2190 ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it); | 2130 ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it); |
| 2191 if (active_it == active_streams_.end()) | 2131 if (active_it == active_streams_.end()) |
| 2192 continue; | 2132 continue; |
| 2193 bytes_pushed_and_unclaimed_count_ += active_it->second.stream->recv_bytes(); | 2133 bytes_pushed_and_unclaimed_count_ += active_it->second->recv_bytes(); |
| 2194 | 2134 |
| 2195 LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM); | 2135 LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM); |
| 2196 // CloseActiveStreamIterator() will remove the stream from | 2136 // CloseActiveStreamIterator() will remove the stream from |
| 2197 // |unclaimed_pushed_streams_|. | 2137 // |unclaimed_pushed_streams_|. |
| 2198 ResetStreamIterator( | 2138 ResetStreamIterator( |
| 2199 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); | 2139 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); |
| 2200 } | 2140 } |
| 2201 | 2141 |
| 2202 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 2142 next_unclaimed_push_stream_sweep_time_ = time_func_() + |
| 2203 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 2143 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2218 fin, stream_id)); | 2158 fin, stream_id)); |
| 2219 } | 2159 } |
| 2220 | 2160 |
| 2221 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2161 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2222 if (it == active_streams_.end()) { | 2162 if (it == active_streams_.end()) { |
| 2223 // NOTE: it may just be that the stream was cancelled. | 2163 // NOTE: it may just be that the stream was cancelled. |
| 2224 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; | 2164 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; |
| 2225 return; | 2165 return; |
| 2226 } | 2166 } |
| 2227 | 2167 |
| 2228 SpdyStream* stream = it->second.stream; | 2168 SpdyStream* stream = it->second; |
| 2229 CHECK_EQ(stream->stream_id(), stream_id); | 2169 CHECK_EQ(stream->stream_id(), stream_id); |
| 2230 | 2170 |
| 2231 stream->AddRawReceivedBytes(last_compressed_frame_len_); | 2171 stream->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2232 last_compressed_frame_len_ = 0; | 2172 last_compressed_frame_len_ = 0; |
| 2233 | 2173 |
| 2174 if (it->second->IsReservedRemote()) { |
| 2175 DCHECK_EQ(SPDY_PUSH_STREAM, stream->type()); |
| 2176 if (max_concurrent_pushed_streams_ && |
| 2177 num_active_pushed_streams_ >= max_concurrent_pushed_streams_) { |
| 2178 ResetStream(stream_id, RST_STREAM_REFUSED_STREAM, |
| 2179 "Stream concurrency limit reached."); |
| 2180 return; |
| 2181 } |
| 2182 |
| 2183 // Will be balanced in DeleteStream. |
| 2184 num_active_pushed_streams_++; |
| 2185 } |
| 2186 |
| 2234 base::Time response_time = base::Time::Now(); | 2187 base::Time response_time = base::Time::Now(); |
| 2235 base::TimeTicks recv_first_byte_time = time_func_(); | 2188 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2236 | 2189 // May invalidate |stream|. |
| 2237 if (it->second.waiting_for_reply_headers_frame) { | 2190 stream->OnHeadersReceived(headers, response_time, recv_first_byte_time); |
| 2238 it->second.waiting_for_reply_headers_frame = false; | |
| 2239 ignore_result(OnInitialResponseHeadersReceived( | |
| 2240 headers, response_time, recv_first_byte_time, stream)); | |
| 2241 } else if (it->second.stream->IsReservedRemote()) { | |
| 2242 ignore_result(OnInitialResponseHeadersReceived( | |
| 2243 headers, response_time, recv_first_byte_time, stream)); | |
| 2244 } else { | |
| 2245 int rv = stream->OnAdditionalResponseHeadersReceived(headers); | |
| 2246 if (rv < 0) { | |
| 2247 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 2248 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | |
| 2249 } | |
| 2250 } | |
| 2251 } | 2191 } |
| 2252 | 2192 |
| 2253 void SpdySession::OnAltSvc( | 2193 void SpdySession::OnAltSvc( |
| 2254 SpdyStreamId stream_id, | 2194 SpdyStreamId stream_id, |
| 2255 base::StringPiece origin, | 2195 base::StringPiece origin, |
| 2256 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) { | 2196 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) { |
| 2257 if (!is_secure_) | 2197 if (!is_secure_) |
| 2258 return; | 2198 return; |
| 2259 | 2199 |
| 2260 url::SchemeHostPort scheme_host_port; | 2200 url::SchemeHostPort scheme_host_port; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2271 gurl.host())) { | 2211 gurl.host())) { |
| 2272 return; | 2212 return; |
| 2273 } | 2213 } |
| 2274 scheme_host_port = url::SchemeHostPort(gurl); | 2214 scheme_host_port = url::SchemeHostPort(gurl); |
| 2275 } else { | 2215 } else { |
| 2276 if (!origin.empty()) | 2216 if (!origin.empty()) |
| 2277 return; | 2217 return; |
| 2278 const ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2218 const ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2279 if (it == active_streams_.end()) | 2219 if (it == active_streams_.end()) |
| 2280 return; | 2220 return; |
| 2281 const GURL& gurl(it->second.stream->url()); | 2221 const GURL& gurl(it->second->url()); |
| 2282 if (!gurl.SchemeIs("https")) | 2222 if (!gurl.SchemeIs("https")) |
| 2283 return; | 2223 return; |
| 2284 scheme_host_port = url::SchemeHostPort(gurl); | 2224 scheme_host_port = url::SchemeHostPort(gurl); |
| 2285 } | 2225 } |
| 2286 | 2226 |
| 2287 AlternativeServiceInfoVector alternative_service_info_vector; | 2227 AlternativeServiceInfoVector alternative_service_info_vector; |
| 2288 alternative_service_info_vector.reserve(altsvc_vector.size()); | 2228 alternative_service_info_vector.reserve(altsvc_vector.size()); |
| 2289 const base::Time now(base::Time::Now()); | 2229 const base::Time now(base::Time::Now()); |
| 2290 for (const SpdyAltSvcWireFormat::AlternativeService& altsvc : altsvc_vector) { | 2230 for (const SpdyAltSvcWireFormat::AlternativeService& altsvc : altsvc_vector) { |
| 2291 const NextProto protocol = NextProtoFromString(altsvc.protocol_id); | 2231 const NextProto protocol = NextProtoFromString(altsvc.protocol_id); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 NetLogEventType::HTTP2_SESSION_RST_STREAM, | 2263 NetLogEventType::HTTP2_SESSION_RST_STREAM, |
| 2324 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); | 2264 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); |
| 2325 | 2265 |
| 2326 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2266 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2327 if (it == active_streams_.end()) { | 2267 if (it == active_streams_.end()) { |
| 2328 // NOTE: it may just be that the stream was cancelled. | 2268 // NOTE: it may just be that the stream was cancelled. |
| 2329 LOG(WARNING) << "Received RST for invalid stream" << stream_id; | 2269 LOG(WARNING) << "Received RST for invalid stream" << stream_id; |
| 2330 return; | 2270 return; |
| 2331 } | 2271 } |
| 2332 | 2272 |
| 2333 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2273 CHECK_EQ(it->second->stream_id(), stream_id); |
| 2334 | 2274 |
| 2335 if (status == RST_STREAM_NO_ERROR) { | 2275 if (status == RST_STREAM_NO_ERROR) { |
| 2336 CloseActiveStreamIterator(it, ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED); | 2276 CloseActiveStreamIterator(it, ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED); |
| 2337 } else if (status == RST_STREAM_REFUSED_STREAM) { | 2277 } else if (status == RST_STREAM_REFUSED_STREAM) { |
| 2338 CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM); | 2278 CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM); |
| 2339 } else if (status == RST_STREAM_HTTP_1_1_REQUIRED) { | 2279 } else if (status == RST_STREAM_HTTP_1_1_REQUIRED) { |
| 2340 // TODO(bnc): Record histogram with number of open streams capped at 50. | 2280 // TODO(bnc): Record histogram with number of open streams capped at 50. |
| 2341 it->second.stream->LogStreamError( | 2281 it->second->LogStreamError( |
| 2342 ERR_HTTP_1_1_REQUIRED, | 2282 ERR_HTTP_1_1_REQUIRED, |
| 2343 base::StringPrintf( | 2283 base::StringPrintf( |
| 2344 "SPDY session closed because of stream with status: %d", status)); | 2284 "SPDY session closed because of stream with status: %d", status)); |
| 2345 DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream."); | 2285 DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream."); |
| 2346 } else { | 2286 } else { |
| 2347 RecordProtocolErrorHistogram( | 2287 RecordProtocolErrorHistogram( |
| 2348 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); | 2288 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); |
| 2349 it->second.stream->LogStreamError( | 2289 it->second->LogStreamError( |
| 2350 ERR_SPDY_PROTOCOL_ERROR, | 2290 ERR_SPDY_PROTOCOL_ERROR, |
| 2351 base::StringPrintf("SPDY stream closed with status: %d", status)); | 2291 base::StringPrintf("SPDY stream closed with status: %d", status)); |
| 2352 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. | 2292 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. |
| 2353 // For now, it doesn't matter much - it is a protocol error. | 2293 // For now, it doesn't matter much - it is a protocol error. |
| 2354 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); | 2294 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); |
| 2355 } | 2295 } |
| 2356 } | 2296 } |
| 2357 | 2297 |
| 2358 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, | 2298 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, |
| 2359 SpdyGoAwayStatus status, | 2299 SpdyGoAwayStatus status, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2433 } else { | 2373 } else { |
| 2434 // WINDOW_UPDATE for a stream. | 2374 // WINDOW_UPDATE for a stream. |
| 2435 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2375 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2436 | 2376 |
| 2437 if (it == active_streams_.end()) { | 2377 if (it == active_streams_.end()) { |
| 2438 // NOTE: it may just be that the stream was cancelled. | 2378 // NOTE: it may just be that the stream was cancelled. |
| 2439 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id; | 2379 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id; |
| 2440 return; | 2380 return; |
| 2441 } | 2381 } |
| 2442 | 2382 |
| 2443 SpdyStream* stream = it->second.stream; | 2383 SpdyStream* stream = it->second; |
| 2444 CHECK_EQ(stream->stream_id(), stream_id); | 2384 CHECK_EQ(stream->stream_id(), stream_id); |
| 2445 | 2385 |
| 2446 if (delta_window_size < 1) { | 2386 if (delta_window_size < 1) { |
| 2447 ResetStreamIterator(it, RST_STREAM_FLOW_CONTROL_ERROR, | 2387 ResetStreamIterator(it, RST_STREAM_FLOW_CONTROL_ERROR, |
| 2448 base::StringPrintf( | 2388 base::StringPrintf( |
| 2449 "Received WINDOW_UPDATE with an invalid " | 2389 "Received WINDOW_UPDATE with an invalid " |
| 2450 "delta_window_size %d", | 2390 "delta_window_size %d", |
| 2451 delta_window_size)); | 2391 delta_window_size)); |
| 2452 return; | 2392 return; |
| 2453 } | 2393 } |
| 2454 | 2394 |
| 2455 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2395 CHECK_EQ(it->second->stream_id(), stream_id); |
| 2456 it->second.stream->IncreaseSendWindowSize(delta_window_size); | 2396 it->second->IncreaseSendWindowSize(delta_window_size); |
| 2457 } | 2397 } |
| 2458 } | 2398 } |
| 2459 | 2399 |
| 2460 bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id, | 2400 void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
| 2461 SpdyStreamId associated_stream_id, | 2401 SpdyStreamId associated_stream_id, |
| 2462 SpdyPriority priority, | 2402 SpdyPriority priority, |
| 2463 SpdyHeaderBlock headers) { | 2403 SpdyHeaderBlock headers) { |
| 2464 // Server-initiated streams should have even sequence numbers. | 2404 // Server-initiated streams should have even sequence numbers. |
| 2465 if ((stream_id & 0x1) != 0) { | 2405 if ((stream_id & 0x1) != 0) { |
| 2466 LOG(WARNING) << "Received invalid push stream id " << stream_id; | 2406 LOG(WARNING) << "Received invalid push stream id " << stream_id; |
| 2467 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Odd push stream id."); | 2407 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Odd push stream id."); |
| 2468 return false; | 2408 return; |
| 2469 } | 2409 } |
| 2470 | 2410 |
| 2471 // Server-initiated streams must be associated with client-initiated streams. | 2411 // Server-initiated streams must be associated with client-initiated streams. |
| 2472 if ((associated_stream_id & 0x1) != 1) { | 2412 if ((associated_stream_id & 0x1) != 1) { |
| 2473 LOG(WARNING) << "Received push stream id " << stream_id | 2413 LOG(WARNING) << "Received push stream id " << stream_id |
| 2474 << " with invalid associated stream id"; | 2414 << " with invalid associated stream id"; |
| 2475 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Push on even stream id."); | 2415 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Push on even stream id."); |
| 2476 return false; | 2416 return; |
| 2477 } | 2417 } |
| 2478 | 2418 |
| 2479 if (stream_id <= last_accepted_push_stream_id_) { | 2419 if (stream_id <= last_accepted_push_stream_id_) { |
| 2480 LOG(WARNING) << "Received push stream id " << stream_id | 2420 LOG(WARNING) << "Received push stream id " << stream_id |
| 2481 << " lesser or equal to the last accepted before"; | 2421 << " lesser or equal to the last accepted before"; |
| 2482 CloseSessionOnError( | 2422 CloseSessionOnError( |
| 2483 ERR_SPDY_PROTOCOL_ERROR, | 2423 ERR_SPDY_PROTOCOL_ERROR, |
| 2484 "New push stream id must be greater than the last accepted."); | 2424 "New push stream id must be greater than the last accepted."); |
| 2485 return false; | 2425 return; |
| 2486 } | 2426 } |
| 2487 | 2427 |
| 2488 if (IsStreamActive(stream_id)) { | 2428 if (IsStreamActive(stream_id)) { |
| 2489 // We should not get here, we'll start going away earlier on | 2429 // We should not get here, we'll start going away earlier on |
| 2490 // |last_seen_push_stream_id_| check. | 2430 // |last_seen_push_stream_id_| check. |
| 2491 LOG(WARNING) << "Received push for active stream " << stream_id; | 2431 LOG(WARNING) << "Received push for active stream " << stream_id; |
| 2492 return false; | 2432 return; |
| 2493 } | 2433 } |
| 2494 | 2434 |
| 2495 last_accepted_push_stream_id_ = stream_id; | 2435 last_accepted_push_stream_id_ = stream_id; |
| 2496 | 2436 |
| 2497 RequestPriority request_priority = | 2437 RequestPriority request_priority = |
| 2498 ConvertSpdyPriorityToRequestPriority(priority); | 2438 ConvertSpdyPriorityToRequestPriority(priority); |
| 2499 | 2439 |
| 2500 if (availability_state_ == STATE_GOING_AWAY) { | 2440 if (availability_state_ == STATE_GOING_AWAY) { |
| 2501 // TODO(akalin): This behavior isn't in the SPDY spec, although it | 2441 // TODO(akalin): This behavior isn't in the SPDY spec, although it |
| 2502 // probably should be. | 2442 // probably should be. |
| 2503 EnqueueResetStreamFrame(stream_id, | 2443 EnqueueResetStreamFrame(stream_id, |
| 2504 request_priority, | 2444 request_priority, |
| 2505 RST_STREAM_REFUSED_STREAM, | 2445 RST_STREAM_REFUSED_STREAM, |
| 2506 "push stream request received when going away"); | 2446 "push stream request received when going away"); |
| 2507 return false; | 2447 return; |
| 2508 } | 2448 } |
| 2509 | 2449 |
| 2510 if (associated_stream_id == 0) { | 2450 if (associated_stream_id == 0) { |
| 2511 // In HTTP/2 0 stream id in PUSH_PROMISE frame leads to framer error and | 2451 // In HTTP/2 0 stream id in PUSH_PROMISE frame leads to framer error and |
| 2512 // session going away. We should never get here. | 2452 // session going away. We should never get here. |
| 2513 std::string description = base::StringPrintf( | 2453 std::string description = base::StringPrintf( |
| 2514 "Received invalid associated stream id %d for pushed stream %d", | 2454 "Received invalid associated stream id %d for pushed stream %d", |
| 2515 associated_stream_id, | 2455 associated_stream_id, |
| 2516 stream_id); | 2456 stream_id); |
| 2517 EnqueueResetStreamFrame( | 2457 EnqueueResetStreamFrame( |
| 2518 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description); | 2458 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description); |
| 2519 return false; | 2459 return; |
| 2520 } | 2460 } |
| 2521 | 2461 |
| 2522 streams_pushed_count_++; | 2462 streams_pushed_count_++; |
| 2523 | 2463 |
| 2524 // TODO(mbelshe): DCHECK that this is a GET method? | 2464 // TODO(mbelshe): DCHECK that this is a GET method? |
| 2525 | 2465 |
| 2526 // Verify that the response had a URL for us. | 2466 // Verify that the response had a URL for us. |
| 2527 GURL gurl = GetUrlFromHeaderBlock(headers); | 2467 GURL gurl = GetUrlFromHeaderBlock(headers); |
| 2528 if (!gurl.is_valid()) { | 2468 if (!gurl.is_valid()) { |
| 2529 EnqueueResetStreamFrame(stream_id, | 2469 EnqueueResetStreamFrame(stream_id, |
| 2530 request_priority, | 2470 request_priority, |
| 2531 RST_STREAM_PROTOCOL_ERROR, | 2471 RST_STREAM_PROTOCOL_ERROR, |
| 2532 "Pushed stream url was invalid: " + gurl.spec()); | 2472 "Pushed stream url was invalid: " + gurl.spec()); |
| 2533 return false; | 2473 return; |
| 2534 } | 2474 } |
| 2535 | 2475 |
| 2536 // Verify we have a valid stream association. | 2476 // Verify we have a valid stream association. |
| 2537 ActiveStreamMap::iterator associated_it = | 2477 ActiveStreamMap::iterator associated_it = |
| 2538 active_streams_.find(associated_stream_id); | 2478 active_streams_.find(associated_stream_id); |
| 2539 if (associated_it == active_streams_.end()) { | 2479 if (associated_it == active_streams_.end()) { |
| 2540 EnqueueResetStreamFrame( | 2480 EnqueueResetStreamFrame( |
| 2541 stream_id, | 2481 stream_id, |
| 2542 request_priority, | 2482 request_priority, |
| 2543 RST_STREAM_INVALID_STREAM, | 2483 RST_STREAM_INVALID_STREAM, |
| 2544 base::StringPrintf("Received push for inactive associated stream %d", | 2484 base::StringPrintf("Received push for inactive associated stream %d", |
| 2545 associated_stream_id)); | 2485 associated_stream_id)); |
| 2546 return false; | 2486 return; |
| 2547 } | 2487 } |
| 2548 | 2488 |
| 2549 DCHECK(gurl.is_valid()); | 2489 DCHECK(gurl.is_valid()); |
| 2550 | 2490 |
| 2551 // Check that the pushed stream advertises the same origin as its associated | 2491 // Check that the pushed stream advertises the same origin as its associated |
| 2552 // stream. Bypass this check if and only if this session is with a SPDY proxy | 2492 // stream. Bypass this check if and only if this session is with a SPDY proxy |
| 2553 // that is trusted explicitly as determined by the |proxy_delegate_| or if the | 2493 // that is trusted explicitly as determined by the |proxy_delegate_| or if the |
| 2554 // proxy is pushing same-origin resources. | 2494 // proxy is pushing same-origin resources. |
| 2555 if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) { | 2495 if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) { |
| 2556 if (proxy_delegate_ && | 2496 if (proxy_delegate_ && |
| 2557 proxy_delegate_->IsTrustedSpdyProxy( | 2497 proxy_delegate_->IsTrustedSpdyProxy( |
| 2558 ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) { | 2498 ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) { |
| 2559 // Disallow pushing of HTTPS content. | 2499 // Disallow pushing of HTTPS content. |
| 2560 if (gurl.SchemeIs("https")) { | 2500 if (gurl.SchemeIs("https")) { |
| 2561 EnqueueResetStreamFrame( | 2501 EnqueueResetStreamFrame( |
| 2562 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2502 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, |
| 2563 base::StringPrintf("Rejected push of cross origin HTTPS content %d " | 2503 base::StringPrintf("Rejected push of cross origin HTTPS content %d " |
| 2564 "from trusted proxy", | 2504 "from trusted proxy", |
| 2565 associated_stream_id)); | 2505 associated_stream_id)); |
| 2566 return false; | 2506 return; |
| 2567 } | 2507 } |
| 2568 } else { | 2508 } else { |
| 2569 GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); | 2509 GURL associated_url(associated_it->second->GetUrlFromHeaders()); |
| 2570 if (associated_url.SchemeIs("https")) { | 2510 if (associated_url.SchemeIs("https")) { |
| 2571 SSLInfo ssl_info; | 2511 SSLInfo ssl_info; |
| 2572 CHECK(GetSSLInfo(&ssl_info)); | 2512 CHECK(GetSSLInfo(&ssl_info)); |
| 2573 if (!gurl.SchemeIs("https") || | 2513 if (!gurl.SchemeIs("https") || |
| 2574 !CanPool(transport_security_state_, ssl_info, associated_url.host(), | 2514 !CanPool(transport_security_state_, ssl_info, associated_url.host(), |
| 2575 gurl.host())) { | 2515 gurl.host())) { |
| 2576 EnqueueResetStreamFrame( | 2516 EnqueueResetStreamFrame( |
| 2577 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2517 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, |
| 2578 base::StringPrintf("Rejected push stream %d on secure connection", | 2518 base::StringPrintf("Rejected push stream %d on secure connection", |
| 2579 associated_stream_id)); | 2519 associated_stream_id)); |
| 2580 return false; | 2520 return; |
| 2581 } | 2521 } |
| 2582 } else { | 2522 } else { |
| 2583 // TODO(bnc): Change SpdyNetworkTransactionTests to use secure sockets. | 2523 // TODO(bnc): Change SpdyNetworkTransactionTests to use secure sockets. |
| 2584 if (associated_url.GetOrigin() != gurl.GetOrigin()) { | 2524 if (associated_url.GetOrigin() != gurl.GetOrigin()) { |
| 2585 EnqueueResetStreamFrame( | 2525 EnqueueResetStreamFrame( |
| 2586 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2526 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, |
| 2587 base::StringPrintf( | 2527 base::StringPrintf( |
| 2588 "Rejected cross origin push stream %d on insecure connection", | 2528 "Rejected cross origin push stream %d on insecure connection", |
| 2589 associated_stream_id)); | 2529 associated_stream_id)); |
| 2590 return false; | 2530 return; |
| 2591 } | 2531 } |
| 2592 } | 2532 } |
| 2593 } | 2533 } |
| 2594 } | 2534 } |
| 2595 | 2535 |
| 2596 // There should not be an existing pushed stream with the same path. | 2536 // There should not be an existing pushed stream with the same path. |
| 2597 UnclaimedPushedStreamContainer::const_iterator pushed_it = | 2537 UnclaimedPushedStreamContainer::const_iterator pushed_it = |
| 2598 unclaimed_pushed_streams_.lower_bound(gurl); | 2538 unclaimed_pushed_streams_.lower_bound(gurl); |
| 2599 if (pushed_it != unclaimed_pushed_streams_.end() && | 2539 if (pushed_it != unclaimed_pushed_streams_.end() && |
| 2600 pushed_it->first == gurl) { | 2540 pushed_it->first == gurl) { |
| 2601 EnqueueResetStreamFrame( | 2541 EnqueueResetStreamFrame( |
| 2602 stream_id, | 2542 stream_id, |
| 2603 request_priority, | 2543 request_priority, |
| 2604 RST_STREAM_PROTOCOL_ERROR, | 2544 RST_STREAM_PROTOCOL_ERROR, |
| 2605 "Received duplicate pushed stream with url: " + gurl.spec()); | 2545 "Received duplicate pushed stream with url: " + gurl.spec()); |
| 2606 return false; | 2546 return; |
| 2607 } | 2547 } |
| 2608 | 2548 |
| 2609 std::unique_ptr<SpdyStream> stream( | 2549 std::unique_ptr<SpdyStream> stream( |
| 2610 new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, request_priority, | 2550 new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, request_priority, |
| 2611 stream_initial_send_window_size_, | 2551 stream_initial_send_window_size_, |
| 2612 stream_max_recv_window_size_, net_log_)); | 2552 stream_max_recv_window_size_, net_log_)); |
| 2613 stream->set_stream_id(stream_id); | 2553 stream->set_stream_id(stream_id); |
| 2614 | 2554 |
| 2615 // In HTTP2 PUSH_PROMISE arrives on associated stream. | 2555 // In HTTP2 PUSH_PROMISE arrives on associated stream. |
| 2616 if (associated_it != active_streams_.end()) { | 2556 if (associated_it != active_streams_.end()) { |
| 2617 associated_it->second.stream->AddRawReceivedBytes( | 2557 associated_it->second->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2618 last_compressed_frame_len_); | |
| 2619 } else { | 2558 } else { |
| 2620 stream->AddRawReceivedBytes(last_compressed_frame_len_); | 2559 stream->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2621 } | 2560 } |
| 2622 | 2561 |
| 2623 last_compressed_frame_len_ = 0; | 2562 last_compressed_frame_len_ = 0; |
| 2624 | 2563 |
| 2625 UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it = | 2564 UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it = |
| 2626 unclaimed_pushed_streams_.insert(pushed_it, gurl, stream_id, | 2565 unclaimed_pushed_streams_.insert(pushed_it, gurl, stream_id, |
| 2627 time_func_()); | 2566 time_func_()); |
| 2628 DCHECK(inserted_pushed_it != pushed_it); | 2567 DCHECK(inserted_pushed_it != pushed_it); |
| 2629 DeleteExpiredPushedStreams(); | 2568 DeleteExpiredPushedStreams(); |
| 2630 | 2569 |
| 2631 InsertActivatedStream(std::move(stream)); | 2570 InsertActivatedStream(std::move(stream)); |
| 2632 | 2571 |
| 2633 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); | 2572 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); |
| 2634 if (active_it == active_streams_.end()) { | 2573 if (active_it == active_streams_.end()) { |
| 2635 NOTREACHED(); | 2574 NOTREACHED(); |
| 2636 return false; | 2575 return; |
| 2637 } | 2576 } |
| 2638 | 2577 |
| 2639 // Notify the push_delegate that a push promise has been received. | 2578 // Notify the push_delegate that a push promise has been received. |
| 2640 if (push_delegate_) { | 2579 if (push_delegate_) { |
| 2641 push_delegate_->OnPush(base::MakeUnique<SpdyServerPushHelper>( | 2580 push_delegate_->OnPush(base::MakeUnique<SpdyServerPushHelper>( |
| 2642 weak_factory_.GetWeakPtr(), gurl)); | 2581 weak_factory_.GetWeakPtr(), gurl)); |
| 2643 } | 2582 } |
| 2644 | 2583 |
| 2645 active_it->second.stream->OnPushPromiseHeadersReceived(std::move(headers)); | 2584 active_it->second->OnPushPromiseHeadersReceived(std::move(headers)); |
| 2646 DCHECK(active_it->second.stream->IsReservedRemote()); | 2585 DCHECK(active_it->second->IsReservedRemote()); |
| 2647 num_pushed_streams_++; | 2586 num_pushed_streams_++; |
| 2648 return true; | 2587 return; |
| 2649 } | 2588 } |
| 2650 | 2589 |
| 2651 void SpdySession::OnPushPromise(SpdyStreamId stream_id, | 2590 void SpdySession::OnPushPromise(SpdyStreamId stream_id, |
| 2652 SpdyStreamId promised_stream_id, | 2591 SpdyStreamId promised_stream_id, |
| 2653 SpdyHeaderBlock headers) { | 2592 SpdyHeaderBlock headers) { |
| 2654 CHECK(in_io_loop_); | 2593 CHECK(in_io_loop_); |
| 2655 | 2594 |
| 2656 if (net_log_.IsCapturing()) { | 2595 if (net_log_.IsCapturing()) { |
| 2657 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_PUSH_PROMISE, | 2596 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_PUSH_PROMISE, |
| 2658 base::Bind(&NetLogSpdyPushPromiseReceivedCallback, | 2597 base::Bind(&NetLogSpdyPushPromiseReceivedCallback, |
| 2659 &headers, stream_id, promised_stream_id)); | 2598 &headers, stream_id, promised_stream_id)); |
| 2660 } | 2599 } |
| 2661 | 2600 |
| 2662 // Any priority will do. | 2601 // Any priority will do. TODO(baranovich): Pass parent stream id priority? |
| 2663 // TODO(baranovich): pass parent stream id priority? | 2602 TryCreatePushStream(promised_stream_id, stream_id, 0, std::move(headers)); |
| 2664 if (!TryCreatePushStream(promised_stream_id, stream_id, 0, | |
| 2665 std::move(headers))) | |
| 2666 return; | |
| 2667 } | 2603 } |
| 2668 | 2604 |
| 2669 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, | 2605 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, |
| 2670 uint32_t delta_window_size) { | 2606 uint32_t delta_window_size) { |
| 2671 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 2607 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 2672 CHECK(it != active_streams_.end()); | 2608 CHECK(it != active_streams_.end()); |
| 2673 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2609 CHECK_EQ(it->second->stream_id(), stream_id); |
| 2674 SendWindowUpdateFrame( | 2610 SendWindowUpdateFrame(stream_id, delta_window_size, it->second->priority()); |
| 2675 stream_id, delta_window_size, it->second.stream->priority()); | |
| 2676 } | 2611 } |
| 2677 | 2612 |
| 2678 void SpdySession::SendInitialData() { | 2613 void SpdySession::SendInitialData() { |
| 2679 DCHECK(enable_sending_initial_data_); | 2614 DCHECK(enable_sending_initial_data_); |
| 2680 | 2615 |
| 2681 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( | 2616 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( |
| 2682 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), | 2617 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), |
| 2683 kHttp2ConnectionHeaderPrefixSize, | 2618 kHttp2ConnectionHeaderPrefixSize, |
| 2684 false /* take_ownership */)); | 2619 false /* take_ownership */)); |
| 2685 // Count the prefix as part of the subsequent SETTINGS frame. | 2620 // Count the prefix as part of the subsequent SETTINGS frame. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2747 NetLogEventType::HTTP2_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, | 2682 NetLogEventType::HTTP2_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, |
| 2748 NetLog::IntCallback("delta_window_size", delta_window_size)); | 2683 NetLog::IntCallback("delta_window_size", delta_window_size)); |
| 2749 break; | 2684 break; |
| 2750 } | 2685 } |
| 2751 } | 2686 } |
| 2752 } | 2687 } |
| 2753 | 2688 |
| 2754 void SpdySession::UpdateStreamsSendWindowSize(int32_t delta_window_size) { | 2689 void SpdySession::UpdateStreamsSendWindowSize(int32_t delta_window_size) { |
| 2755 for (ActiveStreamMap::iterator it = active_streams_.begin(); | 2690 for (ActiveStreamMap::iterator it = active_streams_.begin(); |
| 2756 it != active_streams_.end(); ++it) { | 2691 it != active_streams_.end(); ++it) { |
| 2757 it->second.stream->AdjustSendWindowSize(delta_window_size); | 2692 it->second->AdjustSendWindowSize(delta_window_size); |
| 2758 } | 2693 } |
| 2759 | 2694 |
| 2760 for (CreatedStreamSet::const_iterator it = created_streams_.begin(); | 2695 for (CreatedStreamSet::const_iterator it = created_streams_.begin(); |
| 2761 it != created_streams_.end(); it++) { | 2696 it != created_streams_.end(); it++) { |
| 2762 (*it)->AdjustSendWindowSize(delta_window_size); | 2697 (*it)->AdjustSendWindowSize(delta_window_size); |
| 2763 } | 2698 } |
| 2764 } | 2699 } |
| 2765 | 2700 |
| 2766 void SpdySession::SendPrefacePingIfNoneInFlight() { | 2701 void SpdySession::SendPrefacePingIfNoneInFlight() { |
| 2767 if (pings_in_flight_ || !enable_ping_based_connection_checking_) | 2702 if (pings_in_flight_ || !enable_ping_based_connection_checking_) |
| 2768 return; | 2703 return; |
| 2769 | 2704 |
| 2770 base::TimeTicks now = time_func_(); | 2705 base::TimeTicks now = time_func_(); |
| 2771 // If there is no activity in the session, then send a preface-PING. | 2706 // If there is no activity in the session, then send a preface-PING. |
| 2772 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) | 2707 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) |
| 2773 SendPrefacePing(); | 2708 SendPrefacePing(); |
| 2774 } | 2709 } |
| 2775 | 2710 |
| 2776 void SpdySession::SendPrefacePing() { | 2711 void SpdySession::SendPrefacePing() { |
| 2777 WritePingFrame(next_ping_id_, false); | 2712 WritePingFrame(next_ping_id_, false); |
| 2778 } | 2713 } |
| 2779 | 2714 |
| 2780 void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id, | 2715 void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id, |
| 2781 uint32_t delta_window_size, | 2716 uint32_t delta_window_size, |
| 2782 RequestPriority priority) { | 2717 RequestPriority priority) { |
| 2783 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 2718 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 2784 if (it != active_streams_.end()) { | 2719 if (it != active_streams_.end()) { |
| 2785 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2720 CHECK_EQ(it->second->stream_id(), stream_id); |
| 2786 } else { | 2721 } else { |
| 2787 CHECK_EQ(stream_id, kSessionFlowControlStreamId); | 2722 CHECK_EQ(stream_id, kSessionFlowControlStreamId); |
| 2788 } | 2723 } |
| 2789 | 2724 |
| 2790 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SENT_WINDOW_UPDATE_FRAME, | 2725 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SENT_WINDOW_UPDATE_FRAME, |
| 2791 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, stream_id, | 2726 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, stream_id, |
| 2792 delta_window_size)); | 2727 delta_window_size)); |
| 2793 | 2728 |
| 2794 DCHECK(buffered_spdy_framer_.get()); | 2729 DCHECK(buffered_spdy_framer_.get()); |
| 2795 std::unique_ptr<SpdySerializedFrame> window_update_frame( | 2730 std::unique_ptr<SpdySerializedFrame> window_update_frame( |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3051 #endif | 2986 #endif |
| 3052 | 2987 |
| 3053 SpdyStreamId stream_id = PopStreamToPossiblyResume(); | 2988 SpdyStreamId stream_id = PopStreamToPossiblyResume(); |
| 3054 if (stream_id == 0) | 2989 if (stream_id == 0) |
| 3055 break; | 2990 break; |
| 3056 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 2991 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 3057 // The stream may actually still be send-stalled after this (due | 2992 // The stream may actually still be send-stalled after this (due |
| 3058 // to its own send window) but that's okay -- it'll then be | 2993 // to its own send window) but that's okay -- it'll then be |
| 3059 // resumed once its send window increases. | 2994 // resumed once its send window increases. |
| 3060 if (it != active_streams_.end()) | 2995 if (it != active_streams_.end()) |
| 3061 it->second.stream->PossiblyResumeIfSendStalled(); | 2996 it->second->PossiblyResumeIfSendStalled(); |
| 3062 | 2997 |
| 3063 // The size should decrease unless we got send-stalled again. | 2998 // The size should decrease unless we got send-stalled again. |
| 3064 if (!IsSendStalled()) | 2999 if (!IsSendStalled()) |
| 3065 DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size); | 3000 DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size); |
| 3066 } | 3001 } |
| 3067 } | 3002 } |
| 3068 | 3003 |
| 3069 SpdyStreamId SpdySession::PopStreamToPossiblyResume() { | 3004 SpdyStreamId SpdySession::PopStreamToPossiblyResume() { |
| 3070 for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) { | 3005 for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) { |
| 3071 std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i]; | 3006 std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i]; |
| 3072 if (!queue->empty()) { | 3007 if (!queue->empty()) { |
| 3073 SpdyStreamId stream_id = queue->front(); | 3008 SpdyStreamId stream_id = queue->front(); |
| 3074 queue->pop_front(); | 3009 queue->pop_front(); |
| 3075 return stream_id; | 3010 return stream_id; |
| 3076 } | 3011 } |
| 3077 } | 3012 } |
| 3078 return 0; | 3013 return 0; |
| 3079 } | 3014 } |
| 3080 | 3015 |
| 3081 } // namespace net | 3016 } // namespace net |
| OLD | NEW |