| 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 <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 1998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2009 | 2009 |
| 2010 if (availability_state_ == STATE_GOING_AWAY) { | 2010 if (availability_state_ == STATE_GOING_AWAY) { |
| 2011 // TODO(akalin): This behavior isn't in the SPDY spec, although it | 2011 // TODO(akalin): This behavior isn't in the SPDY spec, although it |
| 2012 // probably should be. | 2012 // probably should be. |
| 2013 EnqueueResetStreamFrame(stream_id, request_priority, | 2013 EnqueueResetStreamFrame(stream_id, request_priority, |
| 2014 RST_STREAM_REFUSED_STREAM, | 2014 RST_STREAM_REFUSED_STREAM, |
| 2015 "OnSyn received when going away"); | 2015 "OnSyn received when going away"); |
| 2016 return; | 2016 return; |
| 2017 } | 2017 } |
| 2018 | 2018 |
| 2019 if (associated_stream_id == 0) { | 2019 // TODO(jgraettinger): SpdyFramer simulates OnSynStream() from HEADERS |
| 2020 // frames, which don't convey associated stream ID. Disable this check |
| 2021 // for now, and re-enable when PUSH_PROMISE is implemented properly. |
| 2022 if (associated_stream_id == 0 && GetProtocolVersion() < SPDY4) { |
| 2020 std::string description = base::StringPrintf( | 2023 std::string description = base::StringPrintf( |
| 2021 "Received invalid OnSyn associated stream id %d for stream %d", | 2024 "Received invalid OnSyn associated stream id %d for stream %d", |
| 2022 associated_stream_id, stream_id); | 2025 associated_stream_id, stream_id); |
| 2023 EnqueueResetStreamFrame(stream_id, request_priority, | 2026 EnqueueResetStreamFrame(stream_id, request_priority, |
| 2024 RST_STREAM_REFUSED_STREAM, description); | 2027 RST_STREAM_REFUSED_STREAM, description); |
| 2025 return; | 2028 return; |
| 2026 } | 2029 } |
| 2027 | 2030 |
| 2028 streams_pushed_count_++; | 2031 streams_pushed_count_++; |
| 2029 | 2032 |
| 2030 // TODO(mbelshe): DCHECK that this is a GET method? | 2033 // TODO(mbelshe): DCHECK that this is a GET method? |
| 2031 | 2034 |
| 2032 // Verify that the response had a URL for us. | 2035 // Verify that the response had a URL for us. |
| 2033 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); | 2036 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); |
| 2034 if (!gurl.is_valid()) { | 2037 if (!gurl.is_valid()) { |
| 2035 EnqueueResetStreamFrame( | 2038 EnqueueResetStreamFrame( |
| 2036 stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, | 2039 stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, |
| 2037 "Pushed stream url was invalid: " + gurl.spec()); | 2040 "Pushed stream url was invalid: " + gurl.spec()); |
| 2038 return; | 2041 return; |
| 2039 } | 2042 } |
| 2040 | 2043 |
| 2041 // Verify we have a valid stream association. | 2044 // Verify we have a valid stream association. |
| 2042 ActiveStreamMap::iterator associated_it = | 2045 ActiveStreamMap::iterator associated_it = |
| 2043 active_streams_.find(associated_stream_id); | 2046 active_streams_.find(associated_stream_id); |
| 2044 if (associated_it == active_streams_.end()) { | 2047 // TODO(jgraettinger): (See PUSH_PROMISE comment above). |
| 2048 if (GetProtocolVersion() < SPDY4 && associated_it == active_streams_.end()) { |
| 2045 EnqueueResetStreamFrame( | 2049 EnqueueResetStreamFrame( |
| 2046 stream_id, request_priority, RST_STREAM_INVALID_STREAM, | 2050 stream_id, request_priority, RST_STREAM_INVALID_STREAM, |
| 2047 base::StringPrintf( | 2051 base::StringPrintf( |
| 2048 "Received OnSyn with inactive associated stream %d", | 2052 "Received OnSyn with inactive associated stream %d", |
| 2049 associated_stream_id)); | 2053 associated_stream_id)); |
| 2050 return; | 2054 return; |
| 2051 } | 2055 } |
| 2052 | 2056 |
| 2053 // Check that the SYN advertises the same origin as its associated stream. | 2057 // Check that the SYN advertises the same origin as its associated stream. |
| 2054 // Bypass this check if and only if this session is with a SPDY proxy that | 2058 // Bypass this check if and only if this session is with a SPDY proxy that |
| 2055 // is trusted explicitly via the --trusted-spdy-proxy switch. | 2059 // is trusted explicitly via the --trusted-spdy-proxy switch. |
| 2056 if (trusted_spdy_proxy_.Equals(host_port_pair())) { | 2060 if (trusted_spdy_proxy_.Equals(host_port_pair())) { |
| 2057 // Disallow pushing of HTTPS content. | 2061 // Disallow pushing of HTTPS content. |
| 2058 if (gurl.SchemeIs("https")) { | 2062 if (gurl.SchemeIs("https")) { |
| 2059 EnqueueResetStreamFrame( | 2063 EnqueueResetStreamFrame( |
| 2060 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2064 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, |
| 2061 base::StringPrintf( | 2065 base::StringPrintf( |
| 2062 "Rejected push of Cross Origin HTTPS content %d", | 2066 "Rejected push of Cross Origin HTTPS content %d", |
| 2063 associated_stream_id)); | 2067 associated_stream_id)); |
| 2064 } | 2068 } |
| 2065 } else { | 2069 } else if (GetProtocolVersion() < SPDY4) { |
| 2070 // TODO(jgraettinger): (See PUSH_PROMISE comment above). |
| 2066 GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); | 2071 GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); |
| 2067 if (associated_url.GetOrigin() != gurl.GetOrigin()) { | 2072 if (associated_url.GetOrigin() != gurl.GetOrigin()) { |
| 2068 EnqueueResetStreamFrame( | 2073 EnqueueResetStreamFrame( |
| 2069 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2074 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, |
| 2070 base::StringPrintf( | 2075 base::StringPrintf( |
| 2071 "Rejected Cross Origin Push Stream %d", | 2076 "Rejected Cross Origin Push Stream %d", |
| 2072 associated_stream_id)); | 2077 associated_stream_id)); |
| 2073 return; | 2078 return; |
| 2074 } | 2079 } |
| 2075 } | 2080 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2179 // NOTE: it may just be that the stream was cancelled. | 2184 // NOTE: it may just be that the stream was cancelled. |
| 2180 return; | 2185 return; |
| 2181 } | 2186 } |
| 2182 | 2187 |
| 2183 SpdyStream* stream = it->second.stream; | 2188 SpdyStream* stream = it->second.stream; |
| 2184 CHECK_EQ(stream->stream_id(), stream_id); | 2189 CHECK_EQ(stream->stream_id(), stream_id); |
| 2185 | 2190 |
| 2186 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); | 2191 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); |
| 2187 last_compressed_frame_len_ = 0; | 2192 last_compressed_frame_len_ = 0; |
| 2188 | 2193 |
| 2194 if (GetProtocolVersion() >= SPDY4) { |
| 2195 const std::string& error = |
| 2196 "SPDY4 wasn't expecting SYN_REPLY."; |
| 2197 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2198 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2199 return; |
| 2200 } |
| 2189 if (!it->second.waiting_for_syn_reply) { | 2201 if (!it->second.waiting_for_syn_reply) { |
| 2190 const std::string& error = | 2202 const std::string& error = |
| 2191 "Received duplicate SYN_REPLY for stream."; | 2203 "Received duplicate SYN_REPLY for stream."; |
| 2192 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2204 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2193 ResetStreamIterator(it, RST_STREAM_STREAM_IN_USE, error); | 2205 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2194 return; | 2206 return; |
| 2195 } | 2207 } |
| 2196 it->second.waiting_for_syn_reply = false; | 2208 it->second.waiting_for_syn_reply = false; |
| 2197 | 2209 |
| 2198 ignore_result(OnInitialResponseHeadersReceived( | 2210 ignore_result(OnInitialResponseHeadersReceived( |
| 2199 headers, response_time, recv_first_byte_time, stream)); | 2211 headers, response_time, recv_first_byte_time, stream)); |
| 2200 } | 2212 } |
| 2201 | 2213 |
| 2202 void SpdySession::OnHeaders(SpdyStreamId stream_id, | 2214 void SpdySession::OnHeaders(SpdyStreamId stream_id, |
| 2203 bool fin, | 2215 bool fin, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2220 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; | 2232 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; |
| 2221 return; | 2233 return; |
| 2222 } | 2234 } |
| 2223 | 2235 |
| 2224 SpdyStream* stream = it->second.stream; | 2236 SpdyStream* stream = it->second.stream; |
| 2225 CHECK_EQ(stream->stream_id(), stream_id); | 2237 CHECK_EQ(stream->stream_id(), stream_id); |
| 2226 | 2238 |
| 2227 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); | 2239 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); |
| 2228 last_compressed_frame_len_ = 0; | 2240 last_compressed_frame_len_ = 0; |
| 2229 | 2241 |
| 2230 int rv = stream->OnAdditionalResponseHeadersReceived(headers); | 2242 if (it->second.waiting_for_syn_reply) { |
| 2231 if (rv < 0) { | 2243 if (GetProtocolVersion() < SPDY4) { |
| 2232 DCHECK_NE(rv, ERR_IO_PENDING); | 2244 const std::string& error = |
| 2233 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | 2245 "Was expecting SYN_REPLY, not HEADERS."; |
| 2246 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2247 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2248 return; |
| 2249 } |
| 2250 base::Time response_time = base::Time::Now(); |
| 2251 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2252 |
| 2253 it->second.waiting_for_syn_reply = false; |
| 2254 ignore_result(OnInitialResponseHeadersReceived( |
| 2255 headers, response_time, recv_first_byte_time, stream)); |
| 2256 } else { |
| 2257 int rv = stream->OnAdditionalResponseHeadersReceived(headers); |
| 2258 if (rv < 0) { |
| 2259 DCHECK_NE(rv, ERR_IO_PENDING); |
| 2260 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); |
| 2261 } |
| 2234 } | 2262 } |
| 2235 } | 2263 } |
| 2236 | 2264 |
| 2237 void SpdySession::OnRstStream(SpdyStreamId stream_id, | 2265 void SpdySession::OnRstStream(SpdyStreamId stream_id, |
| 2238 SpdyRstStreamStatus status) { | 2266 SpdyRstStreamStatus status) { |
| 2239 CHECK(in_io_loop_); | 2267 CHECK(in_io_loop_); |
| 2240 | 2268 |
| 2241 if (availability_state_ == STATE_CLOSED) | 2269 if (availability_state_ == STATE_CLOSED) |
| 2242 return; | 2270 return; |
| 2243 | 2271 |
| (...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2946 if (!queue->empty()) { | 2974 if (!queue->empty()) { |
| 2947 SpdyStreamId stream_id = queue->front(); | 2975 SpdyStreamId stream_id = queue->front(); |
| 2948 queue->pop_front(); | 2976 queue->pop_front(); |
| 2949 return stream_id; | 2977 return stream_id; |
| 2950 } | 2978 } |
| 2951 } | 2979 } |
| 2952 return 0; | 2980 return 0; |
| 2953 } | 2981 } |
| 2954 | 2982 |
| 2955 } // namespace net | 2983 } // namespace net |
| OLD | NEW |