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 |