Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(529)

Side by Side Diff: net/spdy/spdy_session.cc

Issue 2526003002: Disallow multiple HEADERS frames on pushed streams. (Closed)
Patch Set: Rename enum, enum entry, and member. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_pool_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698