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

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

Issue 288313003: Land Recent QUIC Changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src
Patch Set: implemented rch's comments Created 6 years, 7 months 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
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/quic/quic_flags.h" 10 #include "net/quic/quic_flags.h"
11 #include "net/quic/quic_flow_controller.h"
11 #include "net/quic/quic_headers_stream.h" 12 #include "net/quic/quic_headers_stream.h"
12 #include "net/ssl/ssl_info.h" 13 #include "net/ssl/ssl_info.h"
13 14
14 using base::StringPiece; 15 using base::StringPiece;
15 using base::hash_map; 16 using base::hash_map;
16 using base::hash_set; 17 using base::hash_set;
17 using std::make_pair; 18 using std::make_pair;
18 using std::vector; 19 using std::vector;
19 20
20 namespace net { 21 namespace net {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 virtual void OnConnectionClosed( 72 virtual void OnConnectionClosed(
72 QuicErrorCode error, bool from_peer) OVERRIDE { 73 QuicErrorCode error, bool from_peer) OVERRIDE {
73 session_->OnConnectionClosed(error, from_peer); 74 session_->OnConnectionClosed(error, from_peer);
74 // The session will go away, so don't bother with cleanup. 75 // The session will go away, so don't bother with cleanup.
75 } 76 }
76 77
77 virtual void OnWriteBlocked() OVERRIDE { 78 virtual void OnWriteBlocked() OVERRIDE {
78 session_->OnWriteBlocked(); 79 session_->OnWriteBlocked();
79 } 80 }
80 81
81 virtual bool HasPendingWrites() const OVERRIDE { 82 virtual bool WillingAndAbleToWrite() const OVERRIDE {
82 return session_->HasPendingWrites(); 83 return session_->WillingAndAbleToWrite();
83 } 84 }
84 85
85 virtual bool HasPendingHandshake() const OVERRIDE { 86 virtual bool HasPendingHandshake() const OVERRIDE {
86 return session_->HasPendingHandshake(); 87 return session_->HasPendingHandshake();
87 } 88 }
88 89
89 virtual bool HasOpenDataStreams() const OVERRIDE { 90 virtual bool HasOpenDataStreams() const OVERRIDE {
90 return session_->HasOpenDataStreams(); 91 return session_->HasOpenDataStreams();
91 } 92 }
92 93
93 private: 94 private:
94 QuicSession* session_; 95 QuicSession* session_;
95 }; 96 };
96 97
97 QuicSession::QuicSession(QuicConnection* connection, 98 QuicSession::QuicSession(QuicConnection* connection,
99 uint32 max_flow_control_receive_window_bytes,
98 const QuicConfig& config) 100 const QuicConfig& config)
99 : connection_(connection), 101 : connection_(connection),
100 visitor_shim_(new VisitorShim(this)), 102 visitor_shim_(new VisitorShim(this)),
101 config_(config), 103 config_(config),
102 max_open_streams_(config_.max_streams_per_connection()), 104 max_open_streams_(config_.max_streams_per_connection()),
103 next_stream_id_(is_server() ? 2 : 3), 105 next_stream_id_(is_server() ? 2 : 3),
104 largest_peer_created_stream_id_(0), 106 largest_peer_created_stream_id_(0),
105 error_(QUIC_NO_ERROR), 107 error_(QUIC_NO_ERROR),
106 goaway_received_(false), 108 goaway_received_(false),
107 goaway_sent_(false), 109 goaway_sent_(false),
108 has_pending_handshake_(false) { 110 has_pending_handshake_(false),
111 max_flow_control_receive_window_bytes_(
112 max_flow_control_receive_window_bytes) {
113 if (max_flow_control_receive_window_bytes_ < kDefaultFlowControlSendWindow) {
114 LOG(ERROR) << "Initial receive window ("
115 << max_flow_control_receive_window_bytes_
116 << ") cannot be set lower than default ("
117 << kDefaultFlowControlSendWindow << ").";
118 max_flow_control_receive_window_bytes_ = kDefaultFlowControlSendWindow;
119 }
120 flow_controller_.reset(new QuicFlowController(
121 connection_->supported_versions().front(), 0, is_server(),
122 kDefaultFlowControlSendWindow, max_flow_control_receive_window_bytes_,
123 max_flow_control_receive_window_bytes_));
109 124
110 connection_->set_visitor(visitor_shim_.get()); 125 connection_->set_visitor(visitor_shim_.get());
111 connection_->SetFromConfig(config_); 126 connection_->SetFromConfig(config_);
112 if (connection_->connected()) { 127 if (connection_->connected()) {
113 connection_->SetOverallConnectionTimeout( 128 connection_->SetOverallConnectionTimeout(
114 config_.max_time_before_crypto_handshake()); 129 config_.max_time_before_crypto_handshake());
115 } 130 }
116 headers_stream_.reset(new QuicHeadersStream(this)); 131 headers_stream_.reset(new QuicHeadersStream(this));
117 if (!is_server()) { 132 if (!is_server()) {
118 // For version above QUIC v12, the headers stream is stream 3, so the 133 // For version above QUIC v12, the headers stream is stream 3, so the
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't 237 // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
223 // assume that it still exists. 238 // assume that it still exists.
224 QuicStreamId stream_id = frames[i].stream_id; 239 QuicStreamId stream_id = frames[i].stream_id;
225 if (stream_id == 0) { 240 if (stream_id == 0) {
226 // This is a window update that applies to the connection, rather than an 241 // This is a window update that applies to the connection, rather than an
227 // individual stream. 242 // individual stream.
228 DVLOG(1) << ENDPOINT 243 DVLOG(1) << ENDPOINT
229 << "Received connection level flow control window update with " 244 << "Received connection level flow control window update with "
230 "byte offset: " << frames[i].byte_offset; 245 "byte offset: " << frames[i].byte_offset;
231 if (FLAGS_enable_quic_connection_flow_control && 246 if (FLAGS_enable_quic_connection_flow_control &&
232 connection()->flow_controller()->UpdateSendWindowOffset( 247 flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) {
233 frames[i].byte_offset)) {
234 connection_window_updated = true; 248 connection_window_updated = true;
235 } 249 }
236 continue; 250 continue;
237 } 251 }
238 252
239 QuicDataStream* stream = GetDataStream(stream_id); 253 QuicDataStream* stream = GetDataStream(stream_id);
240 if (stream) { 254 if (stream) {
241 stream->OnWindowUpdateFrame(frames[i]); 255 stream->OnWindowUpdateFrame(frames[i]);
242 } 256 }
243 } 257 }
(...skipping 10 matching lines...) Expand all
254 // TODO(rjshade): Compare our flow control receive windows for specified 268 // TODO(rjshade): Compare our flow control receive windows for specified
255 // streams: if we have a large window then maybe something 269 // streams: if we have a large window then maybe something
256 // had gone wrong with the flow control accounting. 270 // had gone wrong with the flow control accounting.
257 DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: " 271 DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: "
258 << frames[i].stream_id; 272 << frames[i].stream_id;
259 } 273 }
260 } 274 }
261 275
262 void QuicSession::OnCanWrite() { 276 void QuicSession::OnCanWrite() {
263 // We limit the number of writes to the number of pending streams. If more 277 // We limit the number of writes to the number of pending streams. If more
264 // streams become pending, HasPendingWrites will be true, which will cause 278 // streams become pending, WillingAndAbleToWrite will be true, which will
265 // the connection to request resumption before yielding to other connections. 279 // cause the connection to request resumption before yielding to other
280 // connections.
266 size_t num_writes = write_blocked_streams_.NumBlockedStreams(); 281 size_t num_writes = write_blocked_streams_.NumBlockedStreams();
282 if (flow_controller_->IsBlocked()) {
283 // If we are connection level flow control blocked, then only allow the
284 // crypto and headers streams to try writing as all other streams will be
285 // blocked.
286 num_writes = 0;
287 if (write_blocked_streams_.crypto_stream_blocked()) {
288 num_writes += 1;
289 }
290 if (write_blocked_streams_.headers_stream_blocked()) {
291 num_writes += 1;
292 }
293 }
267 if (num_writes == 0) { 294 if (num_writes == 0) {
268 return; 295 return;
269 } 296 }
270 297
271 QuicConnection::ScopedPacketBundler ack_bundler( 298 QuicConnection::ScopedPacketBundler ack_bundler(
272 connection_.get(), QuicConnection::NO_ACK); 299 connection_.get(), QuicConnection::NO_ACK);
273 for (size_t i = 0; i < num_writes; ++i) { 300 for (size_t i = 0; i < num_writes; ++i) {
274 if (!write_blocked_streams_.HasWriteBlockedStreams()) { 301 if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
302 write_blocked_streams_.HasWriteBlockedDataStreams())) {
wtc 2014/05/19 18:58:40 Nit: I would simplify this expression with De Morg
ramant (doing other things) 2014/05/20 03:22:32 rjshade: wdyt?
275 // Writing one stream removed another!? Something's broken. 303 // Writing one stream removed another!? Something's broken.
276 LOG(DFATAL) << "WriteBlockedStream is missing"; 304 LOG(DFATAL) << "WriteBlockedStream is missing";
277 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); 305 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
278 return; 306 return;
279 } 307 }
280 if (!connection_->CanWriteStreamData()) { 308 if (!connection_->CanWriteStreamData()) {
281 return; 309 return;
282 } 310 }
283 QuicStreamId stream_id = write_blocked_streams_.PopFront(); 311 QuicStreamId stream_id = write_blocked_streams_.PopFront();
284 if (stream_id == kCryptoStreamId) { 312 if (stream_id == kCryptoStreamId) {
285 has_pending_handshake_ = false; // We just popped it. 313 has_pending_handshake_ = false; // We just popped it.
286 } 314 }
287 ReliableQuicStream* stream = GetStream(stream_id); 315 ReliableQuicStream* stream = GetStream(stream_id);
288 if (stream != NULL && !stream->flow_controller()->IsBlocked()) { 316 if (stream != NULL && !stream->flow_controller()->IsBlocked()) {
289 // If the stream can't write all bytes, it'll re-add itself to the blocked 317 // If the stream can't write all bytes, it'll re-add itself to the blocked
290 // list. 318 // list.
291 stream->OnCanWrite(); 319 stream->OnCanWrite();
292 } 320 }
293 } 321 }
294 } 322 }
295 323
296 bool QuicSession::HasPendingWrites() const { 324 bool QuicSession::WillingAndAbleToWrite() const {
297 return write_blocked_streams_.HasWriteBlockedStreams(); 325 // If the crypto or headers streams are blocked, we want to schedule a write -
326 // they don't get blocked by connection level flow control. Otherwise only
327 // schedule a write if we are not flow control blocked at the connection
328 // level.
329 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
330 (!flow_controller_->IsBlocked() &&
331 write_blocked_streams_.HasWriteBlockedDataStreams());
298 } 332 }
299 333
300 bool QuicSession::HasPendingHandshake() const { 334 bool QuicSession::HasPendingHandshake() const {
301 return has_pending_handshake_; 335 return has_pending_handshake_;
302 } 336 }
303 337
304 bool QuicSession::HasOpenDataStreams() const { 338 bool QuicSession::HasOpenDataStreams() const {
305 return GetNumOpenStreams() > 0; 339 return GetNumOpenStreams() > 0;
306 } 340 }
307 341
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 return; 426 return;
393 } 427 }
394 DataStreamMap::iterator it = stream_map_.begin(); 428 DataStreamMap::iterator it = stream_map_.begin();
395 while (it != stream_map_.end()) { 429 while (it != stream_map_.end()) {
396 it->second->flow_controller()->UpdateSendWindowOffset( 430 it->second->flow_controller()->UpdateSendWindowOffset(
397 new_flow_control_send_window); 431 new_flow_control_send_window);
398 it++; 432 it++;
399 } 433 }
400 434
401 // Update connection level window. 435 // Update connection level window.
402 connection()->flow_controller()->UpdateSendWindowOffset( 436 flow_controller_->UpdateSendWindowOffset(new_flow_control_send_window);
403 new_flow_control_send_window);
404 } 437 }
405 } 438 }
406 439
407 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { 440 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
408 switch (event) { 441 switch (event) {
409 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter 442 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
410 // to QuicSession since it is the glue. 443 // to QuicSession since it is the glue.
411 case ENCRYPTION_FIRST_ESTABLISHED: 444 case ENCRYPTION_FIRST_ESTABLISHED:
412 break; 445 break;
413 446
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 has_pending_handshake_ = true; 617 has_pending_handshake_ = true;
585 // TODO(jar): Be sure to use the highest priority for the crypto stream, 618 // TODO(jar): Be sure to use the highest priority for the crypto stream,
586 // perhaps by adding a "special" priority for it that is higher than 619 // perhaps by adding a "special" priority for it that is higher than
587 // kHighestPriority. 620 // kHighestPriority.
588 priority = kHighestPriority; 621 priority = kHighestPriority;
589 } 622 }
590 write_blocked_streams_.PushBack(id, priority); 623 write_blocked_streams_.PushBack(id, priority);
591 } 624 }
592 625
593 bool QuicSession::HasDataToWrite() const { 626 bool QuicSession::HasDataToWrite() const {
594 return write_blocked_streams_.HasWriteBlockedStreams() || 627 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
595 connection_->HasQueuedData(); 628 write_blocked_streams_.HasWriteBlockedDataStreams() ||
629 connection_->HasQueuedData();
596 } 630 }
597 631
598 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { 632 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const {
599 NOTIMPLEMENTED(); 633 NOTIMPLEMENTED();
600 return false; 634 return false;
601 } 635 }
602 636
603 void QuicSession::PostProcessAfterData() { 637 void QuicSession::PostProcessAfterData() {
604 STLDeleteElements(&closed_streams_); 638 STLDeleteElements(&closed_streams_);
605 closed_streams_.clear(); 639 closed_streams_.clear();
606 } 640 }
607 641
642 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) {
643 if (version < QUIC_VERSION_19) {
644 flow_controller_->Disable();
645 }
646 }
647
608 } // namespace net 648 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698