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_flags.h" | 10 #include "net/quic/quic_flags.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 virtual void OnConnectionClosed( | 72 virtual void OnConnectionClosed( |
73 QuicErrorCode error, bool from_peer) OVERRIDE { | 73 QuicErrorCode error, bool from_peer) OVERRIDE { |
74 session_->OnConnectionClosed(error, from_peer); | 74 session_->OnConnectionClosed(error, from_peer); |
75 // The session will go away, so don't bother with cleanup. | 75 // The session will go away, so don't bother with cleanup. |
76 } | 76 } |
77 | 77 |
78 virtual void OnWriteBlocked() OVERRIDE { | 78 virtual void OnWriteBlocked() OVERRIDE { |
79 session_->OnWriteBlocked(); | 79 session_->OnWriteBlocked(); |
80 } | 80 } |
81 | 81 |
82 virtual bool HasPendingWrites() const OVERRIDE { | 82 virtual bool WillingAndAbleToWrite() const OVERRIDE { |
83 return session_->HasPendingWrites(); | 83 return session_->WillingAndAbleToWrite(); |
84 } | 84 } |
85 | 85 |
86 virtual bool HasPendingHandshake() const OVERRIDE { | 86 virtual bool HasPendingHandshake() const OVERRIDE { |
87 return session_->HasPendingHandshake(); | 87 return session_->HasPendingHandshake(); |
88 } | 88 } |
89 | 89 |
90 virtual bool HasOpenDataStreams() const OVERRIDE { | 90 virtual bool HasOpenDataStreams() const OVERRIDE { |
91 return session_->HasOpenDataStreams(); | 91 return session_->HasOpenDataStreams(); |
92 } | 92 } |
93 | 93 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // TODO(rjshade): Compare our flow control receive windows for specified | 268 // TODO(rjshade): Compare our flow control receive windows for specified |
269 // streams: if we have a large window then maybe something | 269 // streams: if we have a large window then maybe something |
270 // had gone wrong with the flow control accounting. | 270 // had gone wrong with the flow control accounting. |
271 DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: " | 271 DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: " |
272 << frames[i].stream_id; | 272 << frames[i].stream_id; |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 void QuicSession::OnCanWrite() { | 276 void QuicSession::OnCanWrite() { |
277 // 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 |
278 // streams become pending, HasPendingWrites will be true, which will cause | 278 // streams become pending, WillingAndAbleToWrite will be true, which will |
279 // the connection to request resumption before yielding to other connections. | 279 // cause the connection to request resumption before yielding to other |
| 280 // connections. |
280 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 } |
281 if (num_writes == 0) { | 294 if (num_writes == 0) { |
282 return; | 295 return; |
283 } | 296 } |
284 | 297 |
285 QuicConnection::ScopedPacketBundler ack_bundler( | 298 QuicConnection::ScopedPacketBundler ack_bundler( |
286 connection_.get(), QuicConnection::NO_ACK); | 299 connection_.get(), QuicConnection::NO_ACK); |
287 for (size_t i = 0; i < num_writes; ++i) { | 300 for (size_t i = 0; i < num_writes; ++i) { |
288 if (!write_blocked_streams_.HasWriteBlockedStreams()) { | 301 if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
| 302 write_blocked_streams_.HasWriteBlockedDataStreams())) { |
289 // Writing one stream removed another!? Something's broken. | 303 // Writing one stream removed another!? Something's broken. |
290 LOG(DFATAL) << "WriteBlockedStream is missing"; | 304 LOG(DFATAL) << "WriteBlockedStream is missing"; |
291 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); | 305 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
292 return; | 306 return; |
293 } | 307 } |
294 if (!connection_->CanWriteStreamData()) { | 308 if (!connection_->CanWriteStreamData()) { |
295 return; | 309 return; |
296 } | 310 } |
297 QuicStreamId stream_id = write_blocked_streams_.PopFront(); | 311 QuicStreamId stream_id = write_blocked_streams_.PopFront(); |
298 if (stream_id == kCryptoStreamId) { | 312 if (stream_id == kCryptoStreamId) { |
299 has_pending_handshake_ = false; // We just popped it. | 313 has_pending_handshake_ = false; // We just popped it. |
300 } | 314 } |
301 ReliableQuicStream* stream = GetStream(stream_id); | 315 ReliableQuicStream* stream = GetStream(stream_id); |
302 if (stream != NULL && !stream->flow_controller()->IsBlocked()) { | 316 if (stream != NULL && !stream->flow_controller()->IsBlocked()) { |
303 // 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 |
304 // list. | 318 // list. |
305 stream->OnCanWrite(); | 319 stream->OnCanWrite(); |
306 } | 320 } |
307 } | 321 } |
308 } | 322 } |
309 | 323 |
310 bool QuicSession::HasPendingWrites() const { | 324 bool QuicSession::WillingAndAbleToWrite() const { |
311 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()); |
312 } | 332 } |
313 | 333 |
314 bool QuicSession::HasPendingHandshake() const { | 334 bool QuicSession::HasPendingHandshake() const { |
315 return has_pending_handshake_; | 335 return has_pending_handshake_; |
316 } | 336 } |
317 | 337 |
318 bool QuicSession::HasOpenDataStreams() const { | 338 bool QuicSession::HasOpenDataStreams() const { |
319 return GetNumOpenStreams() > 0; | 339 return GetNumOpenStreams() > 0; |
320 } | 340 } |
321 | 341 |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 has_pending_handshake_ = true; | 617 has_pending_handshake_ = true; |
598 // 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, |
599 // 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 |
600 // kHighestPriority. | 620 // kHighestPriority. |
601 priority = kHighestPriority; | 621 priority = kHighestPriority; |
602 } | 622 } |
603 write_blocked_streams_.PushBack(id, priority); | 623 write_blocked_streams_.PushBack(id, priority); |
604 } | 624 } |
605 | 625 |
606 bool QuicSession::HasDataToWrite() const { | 626 bool QuicSession::HasDataToWrite() const { |
607 return write_blocked_streams_.HasWriteBlockedStreams() || | 627 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
608 connection_->HasQueuedData(); | 628 write_blocked_streams_.HasWriteBlockedDataStreams() || |
| 629 connection_->HasQueuedData(); |
609 } | 630 } |
610 | 631 |
611 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { | 632 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { |
612 NOTIMPLEMENTED(); | 633 NOTIMPLEMENTED(); |
613 return false; | 634 return false; |
614 } | 635 } |
615 | 636 |
616 void QuicSession::PostProcessAfterData() { | 637 void QuicSession::PostProcessAfterData() { |
617 STLDeleteElements(&closed_streams_); | 638 STLDeleteElements(&closed_streams_); |
618 closed_streams_.clear(); | 639 closed_streams_.clear(); |
619 } | 640 } |
620 | 641 |
621 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { | 642 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { |
622 if (version < QUIC_VERSION_19) { | 643 if (version < QUIC_VERSION_19) { |
623 flow_controller_->Disable(); | 644 flow_controller_->Disable(); |
624 } | 645 } |
625 } | 646 } |
626 | 647 |
627 } // namespace net | 648 } // namespace net |
OLD | NEW |