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/quic/quic_session.h" | 5 #include "net/quic/quic_session.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "net/quic/crypto/proof_verifier.h" | 8 #include "net/quic/crypto/proof_verifier.h" |
9 #include "net/quic/quic_connection.h" | 9 #include "net/quic/quic_connection.h" |
10 #include "net/quic/quic_flow_controller.h" | 10 #include "net/quic/quic_flow_controller.h" |
11 #include "net/quic/quic_headers_stream.h" | |
12 #include "net/ssl/ssl_info.h" | 11 #include "net/ssl/ssl_info.h" |
13 | 12 |
14 using base::StringPiece; | 13 using base::StringPiece; |
15 using base::hash_map; | 14 using base::hash_map; |
16 using base::hash_set; | 15 using base::hash_set; |
17 using std::make_pair; | 16 using std::make_pair; |
18 using std::map; | 17 using std::map; |
19 using std::max; | 18 using std::max; |
20 using std::string; | 19 using std::string; |
21 using std::vector; | 20 using std::vector; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 void OnWriteBlocked() override { session_->OnWriteBlocked(); } | 81 void OnWriteBlocked() override { session_->OnWriteBlocked(); } |
83 | 82 |
84 bool WillingAndAbleToWrite() const override { | 83 bool WillingAndAbleToWrite() const override { |
85 return session_->WillingAndAbleToWrite(); | 84 return session_->WillingAndAbleToWrite(); |
86 } | 85 } |
87 | 86 |
88 bool HasPendingHandshake() const override { | 87 bool HasPendingHandshake() const override { |
89 return session_->HasPendingHandshake(); | 88 return session_->HasPendingHandshake(); |
90 } | 89 } |
91 | 90 |
92 bool HasOpenDataStreams() const override { | 91 bool HasOpenDynamicStreams() const override { |
93 return session_->HasOpenDataStreams(); | 92 return session_->HasOpenDynamicStreams(); |
94 } | 93 } |
95 | 94 |
96 private: | 95 private: |
97 QuicSession* session_; | 96 QuicSession* session_; |
98 }; | 97 }; |
99 | 98 |
100 QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) | 99 QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) |
101 : connection_(connection), | 100 : connection_(connection), |
102 visitor_shim_(new VisitorShim(this)), | 101 visitor_shim_(new VisitorShim(this)), |
103 config_(config), | 102 config_(config), |
104 max_open_streams_(config_.MaxStreamsPerConnection()), | 103 max_open_streams_(config_.MaxStreamsPerConnection()), |
105 next_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 5), | 104 next_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 3), |
106 largest_peer_created_stream_id_(0), | 105 largest_peer_created_stream_id_( |
| 106 perspective() == Perspective::IS_SERVER ? 1 : 0), |
107 error_(QUIC_NO_ERROR), | 107 error_(QUIC_NO_ERROR), |
108 flow_controller_(connection_.get(), | 108 flow_controller_(connection_.get(), |
109 0, | 109 0, |
110 perspective(), | 110 perspective(), |
111 kMinimumFlowControlSendWindow, | 111 kMinimumFlowControlSendWindow, |
112 config_.GetInitialSessionFlowControlWindowToSend(), | 112 config_.GetInitialSessionFlowControlWindowToSend(), |
113 false), | 113 false), |
114 goaway_received_(false), | 114 goaway_received_(false), |
115 goaway_sent_(false), | 115 goaway_sent_(false), |
116 has_pending_handshake_(false) { | 116 has_pending_handshake_(false) { |
117 } | 117 } |
118 | 118 |
119 void QuicSession::Initialize() { | 119 void QuicSession::Initialize() { |
120 // Crypto stream must exist when Initialize is called. | |
121 DCHECK(GetCryptoStream()); | |
122 | |
123 connection_->set_visitor(visitor_shim_.get()); | 120 connection_->set_visitor(visitor_shim_.get()); |
124 connection_->SetFromConfig(config_); | 121 connection_->SetFromConfig(config_); |
125 headers_stream_.reset(new QuicHeadersStream(this)); | 122 |
| 123 DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); |
| 124 static_stream_map_[kCryptoStreamId] = GetCryptoStream(); |
126 } | 125 } |
127 | 126 |
128 QuicSession::~QuicSession() { | 127 QuicSession::~QuicSession() { |
129 STLDeleteElements(&closed_streams_); | 128 STLDeleteElements(&closed_streams_); |
130 STLDeleteValues(&stream_map_); | 129 STLDeleteValues(&dynamic_stream_map_); |
131 | 130 |
132 DLOG_IF(WARNING, | 131 DLOG_IF(WARNING, |
133 locally_closed_streams_highest_offset_.size() > max_open_streams_) | 132 locally_closed_streams_highest_offset_.size() > max_open_streams_) |
134 << "Surprisingly high number of locally closed streams still waiting for " | 133 << "Surprisingly high number of locally closed streams still waiting for " |
135 "final byte offset: " << locally_closed_streams_highest_offset_.size(); | 134 "final byte offset: " << locally_closed_streams_highest_offset_.size(); |
136 } | 135 } |
137 | 136 |
138 void QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) { | 137 void QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) { |
139 for (size_t i = 0; i < frames.size() && connection_->connected(); ++i) { | 138 for (size_t i = 0; i < frames.size() && connection_->connected(); ++i) { |
140 // TODO(rch) deal with the error case of stream id 0. | 139 // TODO(rch) deal with the error case of stream id 0. |
141 const QuicStreamFrame& frame = frames[i]; | 140 const QuicStreamFrame& frame = frames[i]; |
142 QuicStreamId stream_id = frame.stream_id; | 141 QuicStreamId stream_id = frame.stream_id; |
143 ReliableQuicStream* stream = GetStream(stream_id); | 142 ReliableQuicStream* stream = GetStream(stream_id); |
144 if (!stream) { | 143 if (!stream) { |
145 // The stream no longer exists, but we may still be interested in the | 144 // The stream no longer exists, but we may still be interested in the |
146 // final stream byte offset sent by the peer. A frame with a FIN can give | 145 // final stream byte offset sent by the peer. A frame with a FIN can give |
147 // us this offset. | 146 // us this offset. |
148 if (frame.fin) { | 147 if (frame.fin) { |
149 QuicStreamOffset final_byte_offset = frame.offset + frame.data.size(); | 148 QuicStreamOffset final_byte_offset = frame.offset + frame.data.size(); |
150 UpdateFlowControlOnFinalReceivedByteOffset(stream_id, | 149 UpdateFlowControlOnFinalReceivedByteOffset(stream_id, |
151 final_byte_offset); | 150 final_byte_offset); |
152 } | 151 } |
153 | 152 |
154 continue; | 153 continue; |
155 } | 154 } |
156 stream->OnStreamFrame(frames[i]); | 155 stream->OnStreamFrame(frames[i]); |
157 } | 156 } |
158 } | 157 } |
159 | 158 |
160 void QuicSession::OnStreamHeaders(QuicStreamId stream_id, | |
161 StringPiece headers_data) { | |
162 QuicDataStream* stream = GetDataStream(stream_id); | |
163 if (!stream) { | |
164 // It's quite possible to receive headers after a stream has been reset. | |
165 return; | |
166 } | |
167 stream->OnStreamHeaders(headers_data); | |
168 } | |
169 | |
170 void QuicSession::OnStreamHeadersPriority(QuicStreamId stream_id, | |
171 QuicPriority priority) { | |
172 QuicDataStream* stream = GetDataStream(stream_id); | |
173 if (!stream) { | |
174 // It's quite possible to receive headers after a stream has been reset. | |
175 return; | |
176 } | |
177 stream->OnStreamHeadersPriority(priority); | |
178 } | |
179 | |
180 void QuicSession::OnStreamHeadersComplete(QuicStreamId stream_id, | |
181 bool fin, | |
182 size_t frame_len) { | |
183 QuicDataStream* stream = GetDataStream(stream_id); | |
184 if (!stream) { | |
185 // It's quite possible to receive headers after a stream has been reset. | |
186 return; | |
187 } | |
188 stream->OnStreamHeadersComplete(fin, frame_len); | |
189 } | |
190 | |
191 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { | 159 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { |
192 if (frame.stream_id == kCryptoStreamId) { | 160 if (ContainsKey(static_stream_map_, frame.stream_id)) { |
193 connection()->SendConnectionCloseWithDetails( | 161 connection()->SendConnectionCloseWithDetails( |
194 QUIC_INVALID_STREAM_ID, | 162 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream"); |
195 "Attempt to reset the crypto stream"); | |
196 return; | |
197 } | |
198 if (frame.stream_id == kHeadersStreamId) { | |
199 connection()->SendConnectionCloseWithDetails( | |
200 QUIC_INVALID_STREAM_ID, | |
201 "Attempt to reset the headers stream"); | |
202 return; | 163 return; |
203 } | 164 } |
204 | 165 |
205 QuicDataStream* stream = GetDataStream(frame.stream_id); | 166 ReliableQuicStream* stream = GetDynamicStream(frame.stream_id); |
206 if (!stream) { | 167 if (!stream) { |
207 // The RST frame contains the final byte offset for the stream: we can now | 168 // The RST frame contains the final byte offset for the stream: we can now |
208 // update the connection level flow controller if needed. | 169 // update the connection level flow controller if needed. |
209 UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id, | 170 UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id, |
210 frame.byte_offset); | 171 frame.byte_offset); |
211 return; // Errors are handled by GetStream. | 172 return; // Errors are handled by GetStream. |
212 } | 173 } |
213 | 174 |
214 stream->OnStreamReset(frame); | 175 stream->OnStreamReset(frame); |
215 } | 176 } |
216 | 177 |
217 void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { | 178 void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { |
218 DCHECK(frame.last_good_stream_id < next_stream_id_); | 179 DCHECK(frame.last_good_stream_id < next_stream_id_); |
219 goaway_received_ = true; | 180 goaway_received_ = true; |
220 } | 181 } |
221 | 182 |
222 void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { | 183 void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { |
223 DCHECK(!connection_->connected()); | 184 DCHECK(!connection_->connected()); |
224 if (error_ == QUIC_NO_ERROR) { | 185 if (error_ == QUIC_NO_ERROR) { |
225 error_ = error; | 186 error_ = error; |
226 } | 187 } |
227 | 188 |
228 while (!stream_map_.empty()) { | 189 while (!dynamic_stream_map_.empty()) { |
229 DataStreamMap::iterator it = stream_map_.begin(); | 190 StreamMap::iterator it = dynamic_stream_map_.begin(); |
230 QuicStreamId id = it->first; | 191 QuicStreamId id = it->first; |
231 it->second->OnConnectionClosed(error, from_peer); | 192 it->second->OnConnectionClosed(error, from_peer); |
232 // The stream should call CloseStream as part of OnConnectionClosed. | 193 // The stream should call CloseStream as part of OnConnectionClosed. |
233 if (stream_map_.find(id) != stream_map_.end()) { | 194 if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) { |
234 LOG(DFATAL) << ENDPOINT | 195 LOG(DFATAL) << ENDPOINT |
235 << "Stream failed to close under OnConnectionClosed"; | 196 << "Stream failed to close under OnConnectionClosed"; |
236 CloseStream(id); | 197 CloseStream(id); |
237 } | 198 } |
238 } | 199 } |
239 } | 200 } |
240 | 201 |
241 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { | 202 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { |
242 } | 203 } |
243 | 204 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 // level. | 299 // level. |
339 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || | 300 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
340 (!flow_controller_.IsBlocked() && | 301 (!flow_controller_.IsBlocked() && |
341 write_blocked_streams_.HasWriteBlockedDataStreams()); | 302 write_blocked_streams_.HasWriteBlockedDataStreams()); |
342 } | 303 } |
343 | 304 |
344 bool QuicSession::HasPendingHandshake() const { | 305 bool QuicSession::HasPendingHandshake() const { |
345 return has_pending_handshake_; | 306 return has_pending_handshake_; |
346 } | 307 } |
347 | 308 |
348 bool QuicSession::HasOpenDataStreams() const { | 309 bool QuicSession::HasOpenDynamicStreams() const { |
349 return GetNumOpenStreams() > 0; | 310 return GetNumOpenStreams() > 0; |
350 } | 311 } |
351 | 312 |
352 QuicConsumedData QuicSession::WritevData( | 313 QuicConsumedData QuicSession::WritevData( |
353 QuicStreamId id, | 314 QuicStreamId id, |
354 const IOVector& data, | 315 const IOVector& data, |
355 QuicStreamOffset offset, | 316 QuicStreamOffset offset, |
356 bool fin, | 317 bool fin, |
357 FecProtection fec_protection, | 318 FecProtection fec_protection, |
358 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | 319 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { |
359 return connection_->SendStreamData(id, data, offset, fin, fec_protection, | 320 return connection_->SendStreamData(id, data, offset, fin, fec_protection, |
360 ack_notifier_delegate); | 321 ack_notifier_delegate); |
361 } | 322 } |
362 | 323 |
363 size_t QuicSession::WriteHeaders( | |
364 QuicStreamId id, | |
365 const SpdyHeaderBlock& headers, | |
366 bool fin, | |
367 QuicPriority priority, | |
368 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | |
369 return headers_stream_->WriteHeaders(id, headers, fin, priority, | |
370 ack_notifier_delegate); | |
371 } | |
372 | |
373 void QuicSession::SendRstStream(QuicStreamId id, | 324 void QuicSession::SendRstStream(QuicStreamId id, |
374 QuicRstStreamErrorCode error, | 325 QuicRstStreamErrorCode error, |
375 QuicStreamOffset bytes_written) { | 326 QuicStreamOffset bytes_written) { |
| 327 if (ContainsKey(static_stream_map_, id)) { |
| 328 LOG(DFATAL) << "Cannot send RST for a static stream with ID " << id; |
| 329 return; |
| 330 } |
| 331 |
376 if (connection()->connected()) { | 332 if (connection()->connected()) { |
377 // Only send a RST_STREAM frame if still connected. | 333 // Only send a RST_STREAM frame if still connected. |
378 connection_->SendRstStream(id, error, bytes_written); | 334 connection_->SendRstStream(id, error, bytes_written); |
379 } | 335 } |
380 CloseStreamInner(id, true); | 336 CloseStreamInner(id, true); |
381 } | 337 } |
382 | 338 |
383 void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) { | 339 void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) { |
384 if (goaway_sent_) { | 340 if (goaway_sent_) { |
385 return; | 341 return; |
386 } | 342 } |
387 goaway_sent_ = true; | 343 goaway_sent_ = true; |
388 connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); | 344 connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); |
389 } | 345 } |
390 | 346 |
391 void QuicSession::CloseStream(QuicStreamId stream_id) { | 347 void QuicSession::CloseStream(QuicStreamId stream_id) { |
392 CloseStreamInner(stream_id, false); | 348 CloseStreamInner(stream_id, false); |
393 } | 349 } |
394 | 350 |
395 void QuicSession::CloseStreamInner(QuicStreamId stream_id, | 351 void QuicSession::CloseStreamInner(QuicStreamId stream_id, |
396 bool locally_reset) { | 352 bool locally_reset) { |
397 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; | 353 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; |
398 | 354 |
399 DataStreamMap::iterator it = stream_map_.find(stream_id); | 355 StreamMap::iterator it = dynamic_stream_map_.find(stream_id); |
400 if (it == stream_map_.end()) { | 356 if (it == dynamic_stream_map_.end()) { |
401 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; | 357 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; |
402 return; | 358 return; |
403 } | 359 } |
404 QuicDataStream* stream = it->second; | 360 ReliableQuicStream* stream = it->second; |
405 | 361 |
406 // Tell the stream that a RST has been sent. | 362 // Tell the stream that a RST has been sent. |
407 if (locally_reset) { | 363 if (locally_reset) { |
408 stream->set_rst_sent(true); | 364 stream->set_rst_sent(true); |
409 } | 365 } |
410 | 366 |
411 closed_streams_.push_back(it->second); | 367 closed_streams_.push_back(it->second); |
412 | 368 |
413 // If we haven't received a FIN or RST for this stream, we need to keep track | 369 // If we haven't received a FIN or RST for this stream, we need to keep track |
414 // of the how many bytes the stream's flow controller believes it has | 370 // of the how many bytes the stream's flow controller believes it has |
415 // received, for accurate connection level flow control accounting. | 371 // received, for accurate connection level flow control accounting. |
416 if (!stream->HasFinalReceivedByteOffset()) { | 372 if (!stream->HasFinalReceivedByteOffset()) { |
417 locally_closed_streams_highest_offset_[stream_id] = | 373 locally_closed_streams_highest_offset_[stream_id] = |
418 stream->flow_controller()->highest_received_byte_offset(); | 374 stream->flow_controller()->highest_received_byte_offset(); |
419 } | 375 } |
420 | 376 |
421 stream_map_.erase(it); | 377 dynamic_stream_map_.erase(it); |
422 stream->OnClose(); | 378 stream->OnClose(); |
423 // Decrease the number of streams being emulated when a new one is opened. | 379 // Decrease the number of streams being emulated when a new one is opened. |
424 connection_->SetNumOpenStreams(stream_map_.size()); | 380 connection_->SetNumOpenStreams(dynamic_stream_map_.size()); |
425 } | 381 } |
426 | 382 |
427 void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( | 383 void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( |
428 QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { | 384 QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { |
429 map<QuicStreamId, QuicStreamOffset>::iterator it = | 385 map<QuicStreamId, QuicStreamOffset>::iterator it = |
430 locally_closed_streams_highest_offset_.find(stream_id); | 386 locally_closed_streams_highest_offset_.find(stream_id); |
431 if (it == locally_closed_streams_highest_offset_.end()) { | 387 if (it == locally_closed_streams_highest_offset_.end()) { |
432 return; | 388 return; |
433 } | 389 } |
434 | 390 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 442 } |
487 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) { | 443 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) { |
488 OnNewSessionFlowControlWindow( | 444 OnNewSessionFlowControlWindow( |
489 config_.ReceivedInitialSessionFlowControlWindowBytes()); | 445 config_.ReceivedInitialSessionFlowControlWindowBytes()); |
490 } | 446 } |
491 } | 447 } |
492 | 448 |
493 void QuicSession::EnableAutoTuneReceiveWindow() { | 449 void QuicSession::EnableAutoTuneReceiveWindow() { |
494 flow_controller_.set_auto_tune_receive_window(true); | 450 flow_controller_.set_auto_tune_receive_window(true); |
495 // Inform all existing streams about the new window. | 451 // Inform all existing streams about the new window. |
496 GetCryptoStream()->flow_controller()->set_auto_tune_receive_window(true); | 452 for (auto const& kv : static_stream_map_) { |
497 headers_stream_->flow_controller()->set_auto_tune_receive_window(true); | 453 kv.second->flow_controller()->set_auto_tune_receive_window(true); |
498 for (auto const& kv : stream_map_) { | 454 } |
| 455 for (auto const& kv : dynamic_stream_map_) { |
499 kv.second->flow_controller()->set_auto_tune_receive_window(true); | 456 kv.second->flow_controller()->set_auto_tune_receive_window(true); |
500 } | 457 } |
501 } | 458 } |
502 | 459 |
503 void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) { | 460 void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) { |
504 if (new_window < kMinimumFlowControlSendWindow) { | 461 if (new_window < kMinimumFlowControlSendWindow) { |
505 LOG(ERROR) << "Peer sent us an invalid stream flow control send window: " | 462 LOG(ERROR) << "Peer sent us an invalid stream flow control send window: " |
506 << new_window | 463 << new_window |
507 << ", below default: " << kMinimumFlowControlSendWindow; | 464 << ", below default: " << kMinimumFlowControlSendWindow; |
508 if (connection_->connected()) { | 465 if (connection_->connected()) { |
509 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); | 466 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); |
510 } | 467 } |
511 return; | 468 return; |
512 } | 469 } |
513 | 470 |
514 // Inform all existing streams about the new window. | 471 // Inform all existing streams about the new window. |
515 GetCryptoStream()->UpdateSendWindowOffset(new_window); | 472 for (auto const& kv : static_stream_map_) { |
516 headers_stream_->UpdateSendWindowOffset(new_window); | 473 kv.second->UpdateSendWindowOffset(new_window); |
517 for (auto const& kv : stream_map_) { | 474 } |
| 475 for (auto const& kv : dynamic_stream_map_) { |
518 kv.second->UpdateSendWindowOffset(new_window); | 476 kv.second->UpdateSendWindowOffset(new_window); |
519 } | 477 } |
520 } | 478 } |
521 | 479 |
522 void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) { | 480 void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) { |
523 if (new_window < kMinimumFlowControlSendWindow) { | 481 if (new_window < kMinimumFlowControlSendWindow) { |
524 LOG(ERROR) << "Peer sent us an invalid session flow control send window: " | 482 LOG(ERROR) << "Peer sent us an invalid session flow control send window: " |
525 << new_window | 483 << new_window |
526 << ", below default: " << kMinimumFlowControlSendWindow; | 484 << ", below default: " << kMinimumFlowControlSendWindow; |
527 if (connection_->connected()) { | 485 if (connection_->connected()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 } | 522 } |
565 | 523 |
566 void QuicSession::OnCryptoHandshakeMessageReceived( | 524 void QuicSession::OnCryptoHandshakeMessageReceived( |
567 const CryptoHandshakeMessage& message) { | 525 const CryptoHandshakeMessage& message) { |
568 } | 526 } |
569 | 527 |
570 QuicConfig* QuicSession::config() { | 528 QuicConfig* QuicSession::config() { |
571 return &config_; | 529 return &config_; |
572 } | 530 } |
573 | 531 |
574 void QuicSession::ActivateStream(QuicDataStream* stream) { | 532 void QuicSession::ActivateStream(ReliableQuicStream* stream) { |
575 DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size() | 533 DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size() |
576 << ". activating " << stream->id(); | 534 << ". activating " << stream->id(); |
577 DCHECK_EQ(stream_map_.count(stream->id()), 0u); | 535 DCHECK_EQ(dynamic_stream_map_.count(stream->id()), 0u); |
578 stream_map_[stream->id()] = stream; | 536 dynamic_stream_map_[stream->id()] = stream; |
579 // Increase the number of streams being emulated when a new one is opened. | 537 // Increase the number of streams being emulated when a new one is opened. |
580 connection_->SetNumOpenStreams(stream_map_.size()); | 538 connection_->SetNumOpenStreams(dynamic_stream_map_.size()); |
581 } | 539 } |
582 | 540 |
583 QuicStreamId QuicSession::GetNextStreamId() { | 541 QuicStreamId QuicSession::GetNextStreamId() { |
584 QuicStreamId id = next_stream_id_; | 542 QuicStreamId id = next_stream_id_; |
585 next_stream_id_ += 2; | 543 next_stream_id_ += 2; |
586 return id; | 544 return id; |
587 } | 545 } |
588 | 546 |
589 ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { | 547 ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { |
590 if (stream_id == kCryptoStreamId) { | 548 StreamMap::iterator it = static_stream_map_.find(stream_id); |
591 return GetCryptoStream(); | 549 if (it != static_stream_map_.end()) { |
| 550 return it->second; |
592 } | 551 } |
593 if (stream_id == kHeadersStreamId) { | 552 return GetDynamicStream(stream_id); |
594 return headers_stream_.get(); | |
595 } | |
596 return GetDataStream(stream_id); | |
597 } | 553 } |
598 | 554 |
599 QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) { | 555 ReliableQuicStream* QuicSession::GetDynamicStream( |
600 if (stream_id == kCryptoStreamId) { | 556 const QuicStreamId stream_id) { |
601 DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id"; | 557 if (static_stream_map_.find(stream_id) != static_stream_map_.end()) { |
602 return nullptr; | 558 DLOG(FATAL) << "Attempt to call GetDynamicStream for a static stream"; |
603 } | |
604 if (stream_id == kHeadersStreamId) { | |
605 DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id"; | |
606 return nullptr; | 559 return nullptr; |
607 } | 560 } |
608 | 561 |
609 DataStreamMap::iterator it = stream_map_.find(stream_id); | 562 StreamMap::iterator it = dynamic_stream_map_.find(stream_id); |
610 if (it != stream_map_.end()) { | 563 if (it != dynamic_stream_map_.end()) { |
611 return it->second; | 564 return it->second; |
612 } | 565 } |
613 | 566 |
614 if (IsClosedStream(stream_id)) { | 567 if (IsClosedStream(stream_id)) { |
615 return nullptr; | 568 return nullptr; |
616 } | 569 } |
617 | 570 |
618 if (stream_id % 2 == next_stream_id_ % 2) { | 571 if (stream_id % 2 == next_stream_id_ % 2) { |
619 // We've received a frame for a locally-created stream that is not | 572 // We've received a frame for a locally-created stream that is not |
620 // currently active. This is an error. | 573 // currently active. This is an error. |
621 if (connection()->connected()) { | 574 if (connection()->connected()) { |
622 connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); | 575 connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); |
623 } | 576 } |
624 return nullptr; | 577 return nullptr; |
625 } | 578 } |
626 | 579 |
627 return GetIncomingDataStream(stream_id); | 580 return GetIncomingDynamicStream(stream_id); |
628 } | 581 } |
629 | 582 |
630 QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) { | 583 ReliableQuicStream* QuicSession::GetIncomingDynamicStream( |
| 584 QuicStreamId stream_id) { |
631 if (IsClosedStream(stream_id)) { | 585 if (IsClosedStream(stream_id)) { |
632 return nullptr; | 586 return nullptr; |
633 } | 587 } |
634 | 588 |
635 implicitly_created_streams_.erase(stream_id); | 589 implicitly_created_streams_.erase(stream_id); |
636 if (stream_id > largest_peer_created_stream_id_) { | 590 if (stream_id > largest_peer_created_stream_id_) { |
637 if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { | 591 if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { |
638 // We may already have sent a connection close due to multiple reset | 592 // We may already have sent a connection close due to multiple reset |
639 // streams in the same packet. | 593 // streams in the same packet. |
640 if (connection()->connected()) { | 594 if (connection()->connected()) { |
641 LOG(ERROR) << "Trying to get stream: " << stream_id | 595 LOG(ERROR) << "Trying to get stream: " << stream_id |
642 << ", largest peer created stream: " | 596 << ", largest peer created stream: " |
643 << largest_peer_created_stream_id_ | 597 << largest_peer_created_stream_id_ |
644 << ", max delta: " << kMaxStreamIdDelta; | 598 << ", max delta: " << kMaxStreamIdDelta; |
645 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); | 599 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); |
646 } | 600 } |
647 return nullptr; | 601 return nullptr; |
648 } | 602 } |
649 if (largest_peer_created_stream_id_ == 0 && | |
650 perspective() == Perspective::IS_SERVER) { | |
651 largest_peer_created_stream_id_ = 3; | |
652 } | |
653 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; | 603 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; |
654 id < stream_id; | 604 id < stream_id; |
655 id += 2) { | 605 id += 2) { |
656 implicitly_created_streams_.insert(id); | 606 implicitly_created_streams_.insert(id); |
657 } | 607 } |
658 largest_peer_created_stream_id_ = stream_id; | 608 largest_peer_created_stream_id_ = stream_id; |
659 } | 609 } |
660 QuicDataStream* stream = CreateIncomingDataStream(stream_id); | 610 ReliableQuicStream* stream = CreateIncomingDynamicStream(stream_id); |
661 if (stream == nullptr) { | 611 if (stream == nullptr) { |
662 return nullptr; | 612 return nullptr; |
663 } | 613 } |
664 ActivateStream(stream); | 614 ActivateStream(stream); |
665 return stream; | 615 return stream; |
666 } | 616 } |
667 | 617 |
668 void QuicSession::set_max_open_streams(size_t max_open_streams) { | 618 void QuicSession::set_max_open_streams(size_t max_open_streams) { |
669 DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams; | 619 DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams; |
670 max_open_streams_ = max_open_streams; | 620 max_open_streams_ = max_open_streams; |
671 } | 621 } |
672 | 622 |
673 bool QuicSession::IsClosedStream(QuicStreamId id) { | 623 bool QuicSession::IsClosedStream(QuicStreamId id) { |
674 DCHECK_NE(0u, id); | 624 DCHECK_NE(0u, id); |
675 if (id == kCryptoStreamId) { | 625 if (ContainsKey(static_stream_map_, id) || |
676 return false; | 626 ContainsKey(dynamic_stream_map_, id)) { |
677 } | |
678 if (id == kHeadersStreamId) { | |
679 return false; | |
680 } | |
681 if (ContainsKey(stream_map_, id)) { | |
682 // Stream is active | 627 // Stream is active |
683 return false; | 628 return false; |
684 } | 629 } |
685 if (id % 2 == next_stream_id_ % 2) { | 630 if (id % 2 == next_stream_id_ % 2) { |
686 // Locally created streams are strictly in-order. If the id is in the | 631 // Locally created streams are strictly in-order. If the id is in the |
687 // range of created streams and it's not active, it must have been closed. | 632 // range of created streams and it's not active, it must have been closed. |
688 return id < next_stream_id_; | 633 return id < next_stream_id_; |
689 } | 634 } |
690 // For peer created streams, we also need to consider implicitly created | 635 // For peer created streams, we also need to consider implicitly created |
691 // streams. | 636 // streams. |
692 return id <= largest_peer_created_stream_id_ && | 637 return id <= largest_peer_created_stream_id_ && |
693 !ContainsKey(implicitly_created_streams_, id); | 638 !ContainsKey(implicitly_created_streams_, id); |
694 } | 639 } |
695 | 640 |
696 size_t QuicSession::GetNumOpenStreams() const { | 641 size_t QuicSession::GetNumOpenStreams() const { |
697 return stream_map_.size() + implicitly_created_streams_.size(); | 642 return dynamic_stream_map_.size() + implicitly_created_streams_.size(); |
698 } | 643 } |
699 | 644 |
700 void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { | 645 void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { |
701 #ifndef NDEBUG | 646 #ifndef NDEBUG |
702 ReliableQuicStream* stream = GetStream(id); | 647 ReliableQuicStream* stream = GetStream(id); |
703 if (stream != nullptr) { | 648 if (stream != nullptr) { |
704 LOG_IF(DFATAL, priority != stream->EffectivePriority()) | 649 LOG_IF(DFATAL, priority != stream->EffectivePriority()) |
705 << ENDPOINT << "Stream " << id | 650 << ENDPOINT << "Stream " << id |
706 << "Priorities do not match. Got: " << priority | 651 << "Priorities do not match. Got: " << priority |
707 << " Expected: " << stream->EffectivePriority(); | 652 << " Expected: " << stream->EffectivePriority(); |
(...skipping 27 matching lines...) Expand all Loading... |
735 // A buggy client may fail to send FIN/RSTs. Don't tolerate this. | 680 // A buggy client may fail to send FIN/RSTs. Don't tolerate this. |
736 connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS); | 681 connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS); |
737 } | 682 } |
738 } | 683 } |
739 | 684 |
740 bool QuicSession::IsConnectionFlowControlBlocked() const { | 685 bool QuicSession::IsConnectionFlowControlBlocked() const { |
741 return flow_controller_.IsBlocked(); | 686 return flow_controller_.IsBlocked(); |
742 } | 687 } |
743 | 688 |
744 bool QuicSession::IsStreamFlowControlBlocked() { | 689 bool QuicSession::IsStreamFlowControlBlocked() { |
745 if (headers_stream_->flow_controller()->IsBlocked() || | 690 for (auto const& kv : static_stream_map_) { |
746 GetCryptoStream()->flow_controller()->IsBlocked()) { | |
747 return true; | |
748 } | |
749 for (auto const& kv : stream_map_) { | |
750 if (kv.second->flow_controller()->IsBlocked()) { | 691 if (kv.second->flow_controller()->IsBlocked()) { |
751 return true; | 692 return true; |
752 } | 693 } |
| 694 } |
| 695 for (auto const& kv : dynamic_stream_map_) { |
| 696 if (kv.second->flow_controller()->IsBlocked()) { |
| 697 return true; |
| 698 } |
753 } | 699 } |
754 return false; | 700 return false; |
755 } | 701 } |
756 | 702 |
757 } // namespace net | 703 } // namespace net |
OLD | NEW |