| 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/ssl/ssl_info.h" | 10 #include "net/ssl/ssl_info.h" |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 } | 130 } |
| 131 | 131 |
| 132 for (size_t i = 0; i < frames.size(); ++i) { | 132 for (size_t i = 0; i < frames.size(); ++i) { |
| 133 QuicStreamId stream_id = frames[i].stream_id; | 133 QuicStreamId stream_id = frames[i].stream_id; |
| 134 ReliableQuicStream* stream = GetStream(stream_id); | 134 ReliableQuicStream* stream = GetStream(stream_id); |
| 135 if (!stream) { | 135 if (!stream) { |
| 136 continue; | 136 continue; |
| 137 } | 137 } |
| 138 stream->OnStreamFrame(frames[i]); | 138 stream->OnStreamFrame(frames[i]); |
| 139 | 139 |
| 140 // If the stream had been prematurely closed, and the | 140 // If the stream is a data stream had been prematurely closed, and the |
| 141 // headers are now decompressed, then we are finally finished | 141 // headers are now decompressed, then we are finally finished |
| 142 // with this stream. | 142 // with this stream. |
| 143 if (ContainsKey(zombie_streams_, stream_id) && | 143 if (ContainsKey(zombie_streams_, stream_id) && |
| 144 stream->headers_decompressed()) { | 144 static_cast<QuicDataStream*>(stream)->headers_decompressed()) { |
| 145 CloseZombieStream(stream_id); | 145 CloseZombieStream(stream_id); |
| 146 } | 146 } |
| 147 } | 147 } |
| 148 | 148 |
| 149 while (!decompression_blocked_streams_.empty()) { | 149 while (!decompression_blocked_streams_.empty()) { |
| 150 QuicHeaderId header_id = decompression_blocked_streams_.begin()->first; | 150 QuicHeaderId header_id = decompression_blocked_streams_.begin()->first; |
| 151 if (header_id != decompressor_.current_header_id()) { | 151 if (header_id != decompressor_.current_header_id()) { |
| 152 break; | 152 break; |
| 153 } | 153 } |
| 154 QuicStreamId stream_id = decompression_blocked_streams_.begin()->second; | 154 QuicStreamId stream_id = decompression_blocked_streams_.begin()->second; |
| 155 decompression_blocked_streams_.erase(header_id); | 155 decompression_blocked_streams_.erase(header_id); |
| 156 ReliableQuicStream* stream = GetStream(stream_id); | 156 QuicDataStream* stream = GetDataStream(stream_id); |
| 157 if (!stream) { | 157 if (!stream) { |
| 158 connection()->SendConnectionClose( | 158 connection()->SendConnectionClose( |
| 159 QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED); | 159 QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED); |
| 160 return false; | 160 return false; |
| 161 } | 161 } |
| 162 stream->OnDecompressorAvailable(); | 162 stream->OnDecompressorAvailable(); |
| 163 } | 163 } |
| 164 return true; | 164 return true; |
| 165 } | 165 } |
| 166 | 166 |
| 167 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { | 167 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { |
| 168 ReliableQuicStream* stream = GetStream(frame.stream_id); | 168 if (frame.stream_id == kCryptoStreamId) { |
| 169 connection()->SendConnectionCloseWithDetails( |
| 170 QUIC_INVALID_STREAM_ID, |
| 171 "Attempt to reset the crypto stream"); |
| 172 return; |
| 173 } |
| 174 QuicDataStream* stream = GetDataStream(frame.stream_id); |
| 169 if (!stream) { | 175 if (!stream) { |
| 170 return; // Errors are handled by GetStream. | 176 return; // Errors are handled by GetStream. |
| 171 } | 177 } |
| 172 if (ContainsKey(zombie_streams_, stream->id())) { | 178 if (ContainsKey(zombie_streams_, stream->id())) { |
| 173 // If this was a zombie stream then we close it out now. | 179 // If this was a zombie stream then we close it out now. |
| 174 CloseZombieStream(stream->id()); | 180 CloseZombieStream(stream->id()); |
| 175 // However, since the headers still have not been decompressed, we want to | 181 // However, since the headers still have not been decompressed, we want to |
| 176 // mark it a prematurely closed so that if we ever receive frames | 182 // mark it a prematurely closed so that if we ever receive frames |
| 177 // for this stream we can close the connection. | 183 // for this stream we can close the connection. |
| 178 DCHECK(!stream->headers_decompressed()); | 184 DCHECK(!stream->headers_decompressed()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 191 goaway_received_ = true; | 197 goaway_received_ = true; |
| 192 } | 198 } |
| 193 | 199 |
| 194 void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { | 200 void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { |
| 195 DCHECK(!connection_->connected()); | 201 DCHECK(!connection_->connected()); |
| 196 if (error_ == QUIC_NO_ERROR) { | 202 if (error_ == QUIC_NO_ERROR) { |
| 197 error_ = error; | 203 error_ = error; |
| 198 } | 204 } |
| 199 | 205 |
| 200 while (!stream_map_.empty()) { | 206 while (!stream_map_.empty()) { |
| 201 ReliableStreamMap::iterator it = stream_map_.begin(); | 207 DataStreamMap::iterator it = stream_map_.begin(); |
| 202 QuicStreamId id = it->first; | 208 QuicStreamId id = it->first; |
| 203 it->second->OnConnectionClosed(error, from_peer); | 209 it->second->OnConnectionClosed(error, from_peer); |
| 204 // The stream should call CloseStream as part of OnConnectionClosed. | 210 // The stream should call CloseStream as part of OnConnectionClosed. |
| 205 if (stream_map_.find(id) != stream_map_.end()) { | 211 if (stream_map_.find(id) != stream_map_.end()) { |
| 206 LOG(DFATAL) << ENDPOINT | 212 LOG(DFATAL) << ENDPOINT |
| 207 << "Stream failed to close under OnConnectionClosed"; | 213 << "Stream failed to close under OnConnectionClosed"; |
| 208 CloseStream(id); | 214 CloseStream(id); |
| 209 } | 215 } |
| 210 } | 216 } |
| 211 } | 217 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 } | 275 } |
| 270 | 276 |
| 271 void QuicSession::CloseStream(QuicStreamId stream_id) { | 277 void QuicSession::CloseStream(QuicStreamId stream_id) { |
| 272 CloseStreamInner(stream_id, false); | 278 CloseStreamInner(stream_id, false); |
| 273 } | 279 } |
| 274 | 280 |
| 275 void QuicSession::CloseStreamInner(QuicStreamId stream_id, | 281 void QuicSession::CloseStreamInner(QuicStreamId stream_id, |
| 276 bool locally_reset) { | 282 bool locally_reset) { |
| 277 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; | 283 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; |
| 278 | 284 |
| 279 ReliableStreamMap::iterator it = stream_map_.find(stream_id); | 285 DataStreamMap::iterator it = stream_map_.find(stream_id); |
| 280 if (it == stream_map_.end()) { | 286 if (it == stream_map_.end()) { |
| 281 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; | 287 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; |
| 282 return; | 288 return; |
| 283 } | 289 } |
| 284 ReliableQuicStream* stream = it->second; | 290 QuicDataStream* stream = it->second; |
| 285 if (connection_->connected() && !stream->headers_decompressed()) { | 291 if (connection_->connected() && !stream->headers_decompressed()) { |
| 286 // If the stream is being closed locally (for example a client cancelling | 292 // If the stream is being closed locally (for example a client cancelling |
| 287 // a request before receiving the response) then we need to make sure that | 293 // a request before receiving the response) then we need to make sure that |
| 288 // we keep the stream alive long enough to process any response or | 294 // we keep the stream alive long enough to process any response or |
| 289 // RST_STREAM frames. | 295 // RST_STREAM frames. |
| 290 if (locally_reset && !is_server_) { | 296 if (locally_reset && !is_server_) { |
| 291 AddZombieStream(stream_id); | 297 AddZombieStream(stream_id); |
| 292 return; | 298 return; |
| 293 } | 299 } |
| 294 | 300 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 317 // mark it a prematurely closed so that if we ever receive frames | 323 // mark it a prematurely closed so that if we ever receive frames |
| 318 // for this stream we can close the connection. | 324 // for this stream we can close the connection. |
| 319 AddPrematurelyClosedStream(oldest_zombie_stream_id); | 325 AddPrematurelyClosedStream(oldest_zombie_stream_id); |
| 320 } | 326 } |
| 321 zombie_streams_.insert(make_pair(stream_id, true)); | 327 zombie_streams_.insert(make_pair(stream_id, true)); |
| 322 } | 328 } |
| 323 | 329 |
| 324 void QuicSession::CloseZombieStream(QuicStreamId stream_id) { | 330 void QuicSession::CloseZombieStream(QuicStreamId stream_id) { |
| 325 DCHECK(ContainsKey(zombie_streams_, stream_id)); | 331 DCHECK(ContainsKey(zombie_streams_, stream_id)); |
| 326 zombie_streams_.erase(stream_id); | 332 zombie_streams_.erase(stream_id); |
| 327 ReliableQuicStream* stream = GetStream(stream_id); | 333 QuicDataStream* stream = GetDataStream(stream_id); |
| 328 if (!stream) { | 334 if (!stream) { |
| 329 return; | 335 return; |
| 330 } | 336 } |
| 331 stream_map_.erase(stream_id); | 337 stream_map_.erase(stream_id); |
| 332 stream->OnClose(); | 338 stream->OnClose(); |
| 333 closed_streams_.push_back(stream); | 339 closed_streams_.push_back(stream); |
| 334 } | 340 } |
| 335 | 341 |
| 336 void QuicSession::AddPrematurelyClosedStream(QuicStreamId stream_id) { | 342 void QuicSession::AddPrematurelyClosedStream(QuicStreamId stream_id) { |
| 337 if (prematurely_closed_streams_.size() == | 343 if (prematurely_closed_streams_.size() == |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 } | 389 } |
| 384 | 390 |
| 385 void QuicSession::OnCryptoHandshakeMessageReceived( | 391 void QuicSession::OnCryptoHandshakeMessageReceived( |
| 386 const CryptoHandshakeMessage& message) { | 392 const CryptoHandshakeMessage& message) { |
| 387 } | 393 } |
| 388 | 394 |
| 389 QuicConfig* QuicSession::config() { | 395 QuicConfig* QuicSession::config() { |
| 390 return &config_; | 396 return &config_; |
| 391 } | 397 } |
| 392 | 398 |
| 393 void QuicSession::ActivateStream(ReliableQuicStream* stream) { | 399 void QuicSession::ActivateStream(QuicDataStream* stream) { |
| 394 DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size() | 400 DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size() |
| 395 << ". activating " << stream->id(); | 401 << ". activating " << stream->id(); |
| 396 DCHECK_EQ(stream_map_.count(stream->id()), 0u); | 402 DCHECK_EQ(stream_map_.count(stream->id()), 0u); |
| 397 stream_map_[stream->id()] = stream; | 403 stream_map_[stream->id()] = stream; |
| 398 } | 404 } |
| 399 | 405 |
| 400 QuicStreamId QuicSession::GetNextStreamId() { | 406 QuicStreamId QuicSession::GetNextStreamId() { |
| 401 QuicStreamId id = next_stream_id_; | 407 QuicStreamId id = next_stream_id_; |
| 402 next_stream_id_ += 2; | 408 next_stream_id_ += 2; |
| 403 return id; | 409 return id; |
| 404 } | 410 } |
| 405 | 411 |
| 406 ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { | 412 ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { |
| 407 if (stream_id == kCryptoStreamId) { | 413 if (stream_id == kCryptoStreamId) { |
| 408 return GetCryptoStream(); | 414 return GetCryptoStream(); |
| 409 } | 415 } |
| 416 return GetDataStream(stream_id); |
| 417 } |
| 410 | 418 |
| 411 ReliableStreamMap::iterator it = stream_map_.find(stream_id); | 419 QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) { |
| 420 if (stream_id == kCryptoStreamId) { |
| 421 DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id"; |
| 422 return NULL; |
| 423 } |
| 424 |
| 425 DataStreamMap::iterator it = stream_map_.find(stream_id); |
| 412 if (it != stream_map_.end()) { | 426 if (it != stream_map_.end()) { |
| 413 return it->second; | 427 return it->second; |
| 414 } | 428 } |
| 415 | 429 |
| 416 if (IsClosedStream(stream_id)) { | 430 if (IsClosedStream(stream_id)) { |
| 417 return NULL; | 431 return NULL; |
| 418 } | 432 } |
| 419 | 433 |
| 420 if (stream_id % 2 == next_stream_id_ % 2) { | 434 if (stream_id % 2 == next_stream_id_ % 2) { |
| 421 // We've received a frame for a locally-created stream that is not | 435 // We've received a frame for a locally-created stream that is not |
| 422 // currently active. This is an error. | 436 // currently active. This is an error. |
| 423 connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); | 437 connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); |
| 424 return NULL; | 438 return NULL; |
| 425 } | 439 } |
| 426 | 440 |
| 427 return GetIncomingReliableStream(stream_id); | 441 return GetIncomingReliableStream(stream_id); |
| 428 } | 442 } |
| 429 | 443 |
| 430 ReliableQuicStream* QuicSession::GetIncomingReliableStream( | 444 QuicDataStream* QuicSession::GetIncomingReliableStream( |
| 431 QuicStreamId stream_id) { | 445 QuicStreamId stream_id) { |
| 432 if (IsClosedStream(stream_id)) { | 446 if (IsClosedStream(stream_id)) { |
| 433 return NULL; | 447 return NULL; |
| 434 } | 448 } |
| 435 | 449 |
| 436 if (goaway_sent_) { | 450 if (goaway_sent_) { |
| 437 // We've already sent a GoAway | 451 // We've already sent a GoAway |
| 438 SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY); | 452 SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY); |
| 439 return NULL; | 453 return NULL; |
| 440 } | 454 } |
| 441 | 455 |
| 442 implicitly_created_streams_.erase(stream_id); | 456 implicitly_created_streams_.erase(stream_id); |
| 443 if (stream_id > largest_peer_created_stream_id_) { | 457 if (stream_id > largest_peer_created_stream_id_) { |
| 444 // TODO(rch) add unit test for this | 458 // TODO(rch) add unit test for this |
| 445 if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { | 459 if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { |
| 446 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); | 460 connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); |
| 447 return NULL; | 461 return NULL; |
| 448 } | 462 } |
| 449 if (largest_peer_created_stream_id_ == 0) { | 463 if (largest_peer_created_stream_id_ == 0) { |
| 450 largest_peer_created_stream_id_= 1; | 464 largest_peer_created_stream_id_= 1; |
| 451 } | 465 } |
| 452 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; | 466 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; |
| 453 id < stream_id; | 467 id < stream_id; |
| 454 id += 2) { | 468 id += 2) { |
| 455 implicitly_created_streams_.insert(id); | 469 implicitly_created_streams_.insert(id); |
| 456 } | 470 } |
| 457 largest_peer_created_stream_id_ = stream_id; | 471 largest_peer_created_stream_id_ = stream_id; |
| 458 } | 472 } |
| 459 ReliableQuicStream* stream = CreateIncomingReliableStream(stream_id); | 473 QuicDataStream* stream = CreateIncomingDataStream(stream_id); |
| 460 if (stream == NULL) { | 474 if (stream == NULL) { |
| 461 return NULL; | 475 return NULL; |
| 462 } | 476 } |
| 463 ActivateStream(stream); | 477 ActivateStream(stream); |
| 464 return stream; | 478 return stream; |
| 465 } | 479 } |
| 466 | 480 |
| 467 bool QuicSession::IsClosedStream(QuicStreamId id) { | 481 bool QuicSession::IsClosedStream(QuicStreamId id) { |
| 468 DCHECK_NE(0u, id); | 482 DCHECK_NE(0u, id); |
| 469 if (id == kCryptoStreamId) { | 483 if (id == kCryptoStreamId) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 NOTIMPLEMENTED(); | 532 NOTIMPLEMENTED(); |
| 519 return false; | 533 return false; |
| 520 } | 534 } |
| 521 | 535 |
| 522 void QuicSession::PostProcessAfterData() { | 536 void QuicSession::PostProcessAfterData() { |
| 523 STLDeleteElements(&closed_streams_); | 537 STLDeleteElements(&closed_streams_); |
| 524 closed_streams_.clear(); | 538 closed_streams_.clear(); |
| 525 } | 539 } |
| 526 | 540 |
| 527 } // namespace net | 541 } // namespace net |
| OLD | NEW |