Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: net/quic/quic_session.cc

Issue 100173005: Break out the basic reliable QUIC stream functionality from the (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/quic_session.h ('k') | net/quic/quic_session_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/quic/quic_session.h ('k') | net/quic/quic_session_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698