| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 dict->SetInteger("stream_id", stream_id); | 76 dict->SetInteger("stream_id", stream_id); |
| 77 dict->SetBoolean("has_priority", has_priority); | 77 dict->SetBoolean("has_priority", has_priority); |
| 78 if (has_priority) { | 78 if (has_priority) { |
| 79 dict->SetInteger("parent_stream_id", parent_stream_id); | 79 dict->SetInteger("parent_stream_id", parent_stream_id); |
| 80 dict->SetInteger("weight", weight); | 80 dict->SetInteger("weight", weight); |
| 81 dict->SetBoolean("exclusive", exclusive); | 81 dict->SetBoolean("exclusive", exclusive); |
| 82 } | 82 } |
| 83 return std::move(dict); | 83 return std::move(dict); |
| 84 } | 84 } |
| 85 | 85 |
| 86 std::unique_ptr<base::Value> NetLogSpdySynReplyOrHeadersReceivedCallback( | 86 std::unique_ptr<base::Value> NetLogSpdyHeadersReceivedCallback( |
| 87 const SpdyHeaderBlock* headers, | 87 const SpdyHeaderBlock* headers, |
| 88 bool fin, | 88 bool fin, |
| 89 SpdyStreamId stream_id, | 89 SpdyStreamId stream_id, |
| 90 NetLogCaptureMode capture_mode) { | 90 NetLogCaptureMode capture_mode) { |
| 91 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 91 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 92 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); | 92 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); |
| 93 dict->SetBoolean("fin", fin); | 93 dict->SetBoolean("fin", fin); |
| 94 dict->SetInteger("stream_id", stream_id); | 94 dict->SetInteger("stream_id", stream_id); |
| 95 return std::move(dict); | 95 return std::move(dict); |
| 96 } | 96 } |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 type_ = SPDY_BIDIRECTIONAL_STREAM; | 511 type_ = SPDY_BIDIRECTIONAL_STREAM; |
| 512 session_.reset(); | 512 session_.reset(); |
| 513 stream_.reset(); | 513 stream_.reset(); |
| 514 url_ = GURL(); | 514 url_ = GURL(); |
| 515 priority_ = MINIMUM_PRIORITY; | 515 priority_ = MINIMUM_PRIORITY; |
| 516 net_log_ = BoundNetLog(); | 516 net_log_ = BoundNetLog(); |
| 517 callback_.Reset(); | 517 callback_.Reset(); |
| 518 } | 518 } |
| 519 | 519 |
| 520 SpdySession::ActiveStreamInfo::ActiveStreamInfo() | 520 SpdySession::ActiveStreamInfo::ActiveStreamInfo() |
| 521 : stream(NULL), | 521 : stream(NULL), waiting_for_reply_headers_frame(false) {} |
| 522 waiting_for_syn_reply(false) {} | |
| 523 | 522 |
| 524 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) | 523 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) |
| 525 : stream(stream), | 524 : stream(stream), |
| 526 waiting_for_syn_reply(stream->type() != SPDY_PUSH_STREAM) { | 525 waiting_for_reply_headers_frame(stream->type() != SPDY_PUSH_STREAM) {} |
| 527 } | |
| 528 | 526 |
| 529 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {} | 527 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {} |
| 530 | 528 |
| 531 SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer( | 529 SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer( |
| 532 SpdySession* spdy_session) | 530 SpdySession* spdy_session) |
| 533 : spdy_session_(spdy_session) {} | 531 : spdy_session_(spdy_session) {} |
| 534 SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() { | 532 SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() { |
| 535 } | 533 } |
| 536 | 534 |
| 537 size_t SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) { | 535 size_t SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) { |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 DoDrainSession(ERR_CONNECTION_CLOSED, "Closing idle connection."); | 981 DoDrainSession(ERR_CONNECTION_CLOSED, "Closing idle connection."); |
| 984 } | 982 } |
| 985 // Return false as the socket wasn't immediately closed. | 983 // Return false as the socket wasn't immediately closed. |
| 986 return false; | 984 return false; |
| 987 } | 985 } |
| 988 | 986 |
| 989 void SpdySession::EnqueueStreamWrite( | 987 void SpdySession::EnqueueStreamWrite( |
| 990 const base::WeakPtr<SpdyStream>& stream, | 988 const base::WeakPtr<SpdyStream>& stream, |
| 991 SpdyFrameType frame_type, | 989 SpdyFrameType frame_type, |
| 992 std::unique_ptr<SpdyBufferProducer> producer) { | 990 std::unique_ptr<SpdyBufferProducer> producer) { |
| 993 DCHECK(frame_type == HEADERS || | 991 DCHECK(frame_type == HEADERS || frame_type == DATA); |
| 994 frame_type == DATA || | |
| 995 frame_type == SYN_STREAM); | |
| 996 EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream); | 992 EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream); |
| 997 } | 993 } |
| 998 | 994 |
| 999 std::unique_ptr<SpdySerializedFrame> SpdySession::CreateSynStream( | 995 std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders( |
| 1000 SpdyStreamId stream_id, | 996 SpdyStreamId stream_id, |
| 1001 RequestPriority priority, | 997 RequestPriority priority, |
| 1002 SpdyControlFlags flags, | 998 SpdyControlFlags flags, |
| 1003 SpdyHeaderBlock block) { | 999 SpdyHeaderBlock block) { |
| 1004 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 1000 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 1005 CHECK(it != active_streams_.end()); | 1001 CHECK(it != active_streams_.end()); |
| 1006 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 1002 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 1007 | 1003 |
| 1008 SendPrefacePingIfNoneInFlight(); | 1004 SendPrefacePingIfNoneInFlight(); |
| 1009 | 1005 |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 std::unique_ptr<SpdyBufferProducer> producer; | 1457 std::unique_ptr<SpdyBufferProducer> producer; |
| 1462 base::WeakPtr<SpdyStream> stream; | 1458 base::WeakPtr<SpdyStream> stream; |
| 1463 if (!write_queue_.Dequeue(&frame_type, &producer, &stream)) { | 1459 if (!write_queue_.Dequeue(&frame_type, &producer, &stream)) { |
| 1464 write_state_ = WRITE_STATE_IDLE; | 1460 write_state_ = WRITE_STATE_IDLE; |
| 1465 return ERR_IO_PENDING; | 1461 return ERR_IO_PENDING; |
| 1466 } | 1462 } |
| 1467 | 1463 |
| 1468 if (stream.get()) | 1464 if (stream.get()) |
| 1469 CHECK(!stream->IsClosed()); | 1465 CHECK(!stream->IsClosed()); |
| 1470 | 1466 |
| 1471 // Activate the stream only when sending the SYN_STREAM frame to | 1467 // Activate the stream only when sending the HEADERS frame to |
| 1472 // guarantee monotonically-increasing stream IDs. | 1468 // guarantee monotonically-increasing stream IDs. |
| 1473 if (frame_type == SYN_STREAM) { | 1469 if (frame_type == HEADERS) { |
| 1474 CHECK(stream.get()); | 1470 CHECK(stream.get()); |
| 1475 CHECK_EQ(stream->stream_id(), 0u); | 1471 CHECK_EQ(stream->stream_id(), 0u); |
| 1476 std::unique_ptr<SpdyStream> owned_stream = | 1472 std::unique_ptr<SpdyStream> owned_stream = |
| 1477 ActivateCreatedStream(stream.get()); | 1473 ActivateCreatedStream(stream.get()); |
| 1478 InsertActivatedStream(std::move(owned_stream)); | 1474 InsertActivatedStream(std::move(owned_stream)); |
| 1479 | 1475 |
| 1480 if (stream_hi_water_mark_ > kLastStreamId) { | 1476 if (stream_hi_water_mark_ > kLastStreamId) { |
| 1481 CHECK_EQ(stream->stream_id(), kLastStreamId); | 1477 CHECK_EQ(stream->stream_id(), kLastStreamId); |
| 1482 // We've exhausted the stream ID space, and no new streams may be | 1478 // We've exhausted the stream ID space, and no new streams may be |
| 1483 // created after this one. | 1479 // created after this one. |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2030 | 2026 |
| 2031 // By the time data comes in, the stream may already be inactive. | 2027 // By the time data comes in, the stream may already be inactive. |
| 2032 if (it == active_streams_.end()) | 2028 if (it == active_streams_.end()) |
| 2033 return; | 2029 return; |
| 2034 | 2030 |
| 2035 SpdyStream* stream = it->second.stream; | 2031 SpdyStream* stream = it->second.stream; |
| 2036 CHECK_EQ(stream->stream_id(), stream_id); | 2032 CHECK_EQ(stream->stream_id(), stream_id); |
| 2037 | 2033 |
| 2038 stream->AddRawReceivedBytes(len); | 2034 stream->AddRawReceivedBytes(len); |
| 2039 | 2035 |
| 2040 if (it->second.waiting_for_syn_reply) { | 2036 if (it->second.waiting_for_reply_headers_frame) { |
| 2041 const std::string& error = "Data received before SYN_REPLY."; | 2037 const std::string& error = "DATA received before HEADERS."; |
| 2042 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2038 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2043 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | 2039 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2044 return; | 2040 return; |
| 2045 } | 2041 } |
| 2046 | 2042 |
| 2047 stream->OnDataReceived(std::move(buffer)); | 2043 stream->OnDataReceived(std::move(buffer)); |
| 2048 } | 2044 } |
| 2049 | 2045 |
| 2050 void SpdySession::OnStreamEnd(SpdyStreamId stream_id) { | 2046 void SpdySession::OnStreamEnd(SpdyStreamId stream_id) { |
| 2051 CHECK(in_io_loop_); | 2047 CHECK(in_io_loop_); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2063 | 2059 |
| 2064 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2060 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2065 | 2061 |
| 2066 // By the time data comes in, the stream may already be inactive. | 2062 // By the time data comes in, the stream may already be inactive. |
| 2067 if (it == active_streams_.end()) | 2063 if (it == active_streams_.end()) |
| 2068 return; | 2064 return; |
| 2069 | 2065 |
| 2070 SpdyStream* stream = it->second.stream; | 2066 SpdyStream* stream = it->second.stream; |
| 2071 CHECK_EQ(stream->stream_id(), stream_id); | 2067 CHECK_EQ(stream->stream_id(), stream_id); |
| 2072 | 2068 |
| 2073 if (it->second.waiting_for_syn_reply) { | 2069 if (it->second.waiting_for_reply_headers_frame) { |
| 2074 const std::string& error = "Data received before SYN_REPLY."; | 2070 const std::string& error = "DATA received before HEADERS."; |
| 2075 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2071 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2076 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | 2072 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2077 return; | 2073 return; |
| 2078 } | 2074 } |
| 2079 | 2075 |
| 2080 stream->OnDataReceived(std::move(buffer)); | 2076 stream->OnDataReceived(std::move(buffer)); |
| 2081 } | 2077 } |
| 2082 | 2078 |
| 2083 void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) { | 2079 void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) { |
| 2084 CHECK(in_io_loop_); | 2080 CHECK(in_io_loop_); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2129 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTING, | 2125 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTING, |
| 2130 base::Bind(&NetLogSpdySettingCallback, id, | 2126 base::Bind(&NetLogSpdySettingCallback, id, |
| 2131 static_cast<SpdySettingsFlags>(flags), value)); | 2127 static_cast<SpdySettingsFlags>(flags), value)); |
| 2132 } | 2128 } |
| 2133 | 2129 |
| 2134 void SpdySession::OnSendCompressedFrame( | 2130 void SpdySession::OnSendCompressedFrame( |
| 2135 SpdyStreamId stream_id, | 2131 SpdyStreamId stream_id, |
| 2136 SpdyFrameType type, | 2132 SpdyFrameType type, |
| 2137 size_t payload_len, | 2133 size_t payload_len, |
| 2138 size_t frame_len) { | 2134 size_t frame_len) { |
| 2139 if (type != SYN_STREAM && type != HEADERS) | 2135 if (type != HEADERS) |
| 2140 return; | 2136 return; |
| 2141 | 2137 |
| 2142 DCHECK(buffered_spdy_framer_.get()); | 2138 DCHECK(buffered_spdy_framer_.get()); |
| 2143 size_t compressed_len = | 2139 size_t compressed_len = |
| 2144 frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize(); | 2140 frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize(); |
| 2145 | 2141 |
| 2146 if (payload_len) { | 2142 if (payload_len) { |
| 2147 // Make sure we avoid early decimal truncation. | 2143 // Make sure we avoid early decimal truncation. |
| 2148 int compression_pct = 100 - (100 * compressed_len) / payload_len; | 2144 int compression_pct = 100 - (100 * compressed_len) / payload_len; |
| 2149 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", | 2145 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2234 bool has_priority, | 2230 bool has_priority, |
| 2235 int weight, | 2231 int weight, |
| 2236 SpdyStreamId parent_stream_id, | 2232 SpdyStreamId parent_stream_id, |
| 2237 bool exclusive, | 2233 bool exclusive, |
| 2238 bool fin, | 2234 bool fin, |
| 2239 const SpdyHeaderBlock& headers) { | 2235 const SpdyHeaderBlock& headers) { |
| 2240 CHECK(in_io_loop_); | 2236 CHECK(in_io_loop_); |
| 2241 | 2237 |
| 2242 if (net_log().IsCapturing()) { | 2238 if (net_log().IsCapturing()) { |
| 2243 net_log().AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_HEADERS, | 2239 net_log().AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_HEADERS, |
| 2244 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, | 2240 base::Bind(&NetLogSpdyHeadersReceivedCallback, &headers, |
| 2245 &headers, fin, stream_id)); | 2241 fin, stream_id)); |
| 2246 } | 2242 } |
| 2247 | 2243 |
| 2248 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2244 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2249 if (it == active_streams_.end()) { | 2245 if (it == active_streams_.end()) { |
| 2250 // NOTE: it may just be that the stream was cancelled. | 2246 // NOTE: it may just be that the stream was cancelled. |
| 2251 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; | 2247 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; |
| 2252 return; | 2248 return; |
| 2253 } | 2249 } |
| 2254 | 2250 |
| 2255 SpdyStream* stream = it->second.stream; | 2251 SpdyStream* stream = it->second.stream; |
| 2256 CHECK_EQ(stream->stream_id(), stream_id); | 2252 CHECK_EQ(stream->stream_id(), stream_id); |
| 2257 | 2253 |
| 2258 stream->AddRawReceivedBytes(last_compressed_frame_len_); | 2254 stream->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2259 last_compressed_frame_len_ = 0; | 2255 last_compressed_frame_len_ = 0; |
| 2260 | 2256 |
| 2261 base::Time response_time = base::Time::Now(); | 2257 base::Time response_time = base::Time::Now(); |
| 2262 base::TimeTicks recv_first_byte_time = time_func_(); | 2258 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2263 | 2259 |
| 2264 if (it->second.waiting_for_syn_reply) { | 2260 if (it->second.waiting_for_reply_headers_frame) { |
| 2265 it->second.waiting_for_syn_reply = false; | 2261 it->second.waiting_for_reply_headers_frame = false; |
| 2266 ignore_result(OnInitialResponseHeadersReceived( | 2262 ignore_result(OnInitialResponseHeadersReceived( |
| 2267 headers, response_time, recv_first_byte_time, stream)); | 2263 headers, response_time, recv_first_byte_time, stream)); |
| 2268 } else if (it->second.stream->IsReservedRemote()) { | 2264 } else if (it->second.stream->IsReservedRemote()) { |
| 2269 ignore_result(OnInitialResponseHeadersReceived( | 2265 ignore_result(OnInitialResponseHeadersReceived( |
| 2270 headers, response_time, recv_first_byte_time, stream)); | 2266 headers, response_time, recv_first_byte_time, stream)); |
| 2271 } else { | 2267 } else { |
| 2272 int rv = stream->OnAdditionalResponseHeadersReceived(headers); | 2268 int rv = stream->OnAdditionalResponseHeadersReceived(headers); |
| 2273 if (rv < 0) { | 2269 if (rv < 0) { |
| 2274 DCHECK_NE(rv, ERR_IO_PENDING); | 2270 DCHECK_NE(rv, ERR_IO_PENDING); |
| 2275 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | 2271 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); |
| (...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3150 if (!queue->empty()) { | 3146 if (!queue->empty()) { |
| 3151 SpdyStreamId stream_id = queue->front(); | 3147 SpdyStreamId stream_id = queue->front(); |
| 3152 queue->pop_front(); | 3148 queue->pop_front(); |
| 3153 return stream_id; | 3149 return stream_id; |
| 3154 } | 3150 } |
| 3155 } | 3151 } |
| 3156 return 0; | 3152 return 0; |
| 3157 } | 3153 } |
| 3158 | 3154 |
| 3159 } // namespace net | 3155 } // namespace net |
| OLD | NEW |