| 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 |