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 "base/strings/stringprintf.h" |
8 #include "net/quic/crypto/proof_verifier.h" | 9 #include "net/quic/crypto/proof_verifier.h" |
9 #include "net/quic/quic_connection.h" | 10 #include "net/quic/quic_connection.h" |
10 #include "net/quic/quic_flags.h" | 11 #include "net/quic/quic_flags.h" |
11 #include "net/quic/quic_flow_controller.h" | 12 #include "net/quic/quic_flow_controller.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; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 return; | 398 return; |
398 } | 399 } |
399 | 400 |
400 DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset | 401 DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset |
401 << " for stream " << stream_id; | 402 << " for stream " << stream_id; |
402 QuicByteCount offset_diff = final_byte_offset - it->second; | 403 QuicByteCount offset_diff = final_byte_offset - it->second; |
403 if (flow_controller_.UpdateHighestReceivedOffset( | 404 if (flow_controller_.UpdateHighestReceivedOffset( |
404 flow_controller_.highest_received_byte_offset() + offset_diff)) { | 405 flow_controller_.highest_received_byte_offset() + offset_diff)) { |
405 // If the final offset violates flow control, close the connection now. | 406 // If the final offset violates flow control, close the connection now. |
406 if (flow_controller_.FlowControlViolation()) { | 407 if (flow_controller_.FlowControlViolation()) { |
407 connection_->SendConnectionClose( | 408 connection_->SendConnectionCloseWithDetails( |
408 QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA); | 409 QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, |
| 410 "Connection level flow control violation"); |
409 return; | 411 return; |
410 } | 412 } |
411 } | 413 } |
412 | 414 |
413 flow_controller_.AddBytesConsumed(offset_diff); | 415 flow_controller_.AddBytesConsumed(offset_diff); |
414 locally_closed_streams_highest_offset_.erase(it); | 416 locally_closed_streams_highest_offset_.erase(it); |
415 if (IsIncomingStream(stream_id)) { | 417 if (IsIncomingStream(stream_id)) { |
416 --num_locally_closed_incoming_streams_highest_offset_; | 418 --num_locally_closed_incoming_streams_highest_offset_; |
417 } | 419 } |
418 } | 420 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window); | 510 kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window); |
509 } | 511 } |
510 } | 512 } |
511 | 513 |
512 void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) { | 514 void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) { |
513 if (new_window < kMinimumFlowControlSendWindow) { | 515 if (new_window < kMinimumFlowControlSendWindow) { |
514 LOG(ERROR) << "Peer sent us an invalid stream flow control send window: " | 516 LOG(ERROR) << "Peer sent us an invalid stream flow control send window: " |
515 << new_window | 517 << new_window |
516 << ", below default: " << kMinimumFlowControlSendWindow; | 518 << ", below default: " << kMinimumFlowControlSendWindow; |
517 if (connection_->connected()) { | 519 if (connection_->connected()) { |
518 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); | 520 connection_->SendConnectionCloseWithDetails( |
| 521 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low"); |
519 } | 522 } |
520 return; | 523 return; |
521 } | 524 } |
522 | 525 |
523 // Inform all existing streams about the new window. | 526 // Inform all existing streams about the new window. |
524 for (auto const& kv : static_stream_map_) { | 527 for (auto const& kv : static_stream_map_) { |
525 kv.second->UpdateSendWindowOffset(new_window); | 528 kv.second->UpdateSendWindowOffset(new_window); |
526 } | 529 } |
527 for (auto const& kv : dynamic_stream_map_) { | 530 for (auto const& kv : dynamic_stream_map_) { |
528 kv.second->UpdateSendWindowOffset(new_window); | 531 kv.second->UpdateSendWindowOffset(new_window); |
529 } | 532 } |
530 } | 533 } |
531 | 534 |
532 void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) { | 535 void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) { |
533 if (new_window < kMinimumFlowControlSendWindow) { | 536 if (new_window < kMinimumFlowControlSendWindow) { |
534 LOG(ERROR) << "Peer sent us an invalid session flow control send window: " | 537 LOG(ERROR) << "Peer sent us an invalid session flow control send window: " |
535 << new_window | 538 << new_window |
536 << ", below default: " << kMinimumFlowControlSendWindow; | 539 << ", below default: " << kMinimumFlowControlSendWindow; |
537 if (connection_->connected()) { | 540 if (connection_->connected()) { |
538 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); | 541 connection_->SendConnectionCloseWithDetails( |
| 542 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New connection window too low"); |
539 } | 543 } |
540 return; | 544 return; |
541 } | 545 } |
542 | 546 |
543 flow_controller_.UpdateSendWindowOffset(new_window); | 547 flow_controller_.UpdateSendWindowOffset(new_window); |
544 } | 548 } |
545 | 549 |
546 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { | 550 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { |
547 switch (event) { | 551 switch (event) { |
548 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter | 552 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 void QuicSession::StreamDraining(QuicStreamId stream_id) { | 621 void QuicSession::StreamDraining(QuicStreamId stream_id) { |
618 DCHECK(ContainsKey(dynamic_stream_map_, stream_id)); | 622 DCHECK(ContainsKey(dynamic_stream_map_, stream_id)); |
619 if (!ContainsKey(draining_streams_, stream_id)) { | 623 if (!ContainsKey(draining_streams_, stream_id)) { |
620 draining_streams_.insert(stream_id); | 624 draining_streams_.insert(stream_id); |
621 if (IsIncomingStream(stream_id)) { | 625 if (IsIncomingStream(stream_id)) { |
622 ++num_draining_incoming_streams_; | 626 ++num_draining_incoming_streams_; |
623 } | 627 } |
624 } | 628 } |
625 } | 629 } |
626 | 630 |
627 void QuicSession::CloseConnection(QuicErrorCode error) { | 631 void QuicSession::CloseConnectionWithDetails(QuicErrorCode error, |
| 632 const char* details) { |
628 if (connection()->connected()) { | 633 if (connection()->connected()) { |
629 connection()->SendConnectionClose(error); | 634 connection()->SendConnectionCloseWithDetails(error, details); |
630 } | 635 } |
631 } | 636 } |
632 | 637 |
633 ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( | 638 ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( |
634 const QuicStreamId stream_id) { | 639 const QuicStreamId stream_id) { |
635 if (ContainsKey(static_stream_map_, stream_id)) { | 640 if (ContainsKey(static_stream_map_, stream_id)) { |
636 DLOG(FATAL) | 641 DLOG(FATAL) |
637 << "Attempt to call GetOrCreateDynamicStream for a static stream"; | 642 << "Attempt to call GetOrCreateDynamicStream for a static stream"; |
638 return nullptr; | 643 return nullptr; |
639 } | 644 } |
640 | 645 |
641 StreamMap::iterator it = dynamic_stream_map_.find(stream_id); | 646 StreamMap::iterator it = dynamic_stream_map_.find(stream_id); |
642 if (it != dynamic_stream_map_.end()) { | 647 if (it != dynamic_stream_map_.end()) { |
643 return it->second; | 648 return it->second; |
644 } | 649 } |
645 | 650 |
646 if (IsClosedStream(stream_id)) { | 651 if (IsClosedStream(stream_id)) { |
647 return nullptr; | 652 return nullptr; |
648 } | 653 } |
649 | 654 |
650 if (!IsIncomingStream(stream_id)) { | 655 if (!IsIncomingStream(stream_id)) { |
651 // Received a frame for a locally-created stream that is not currently | 656 // Received a frame for a locally-created stream that is not currently |
652 // active. This is an error. | 657 // active. This is an error. |
653 CloseConnection(QUIC_INVALID_STREAM_ID); | 658 CloseConnectionWithDetails(QUIC_INVALID_STREAM_ID, |
| 659 "Data for nonexistent stream"); |
654 return nullptr; | 660 return nullptr; |
655 } | 661 } |
656 | 662 |
657 available_streams_.erase(stream_id); | 663 available_streams_.erase(stream_id); |
658 | 664 |
659 if (stream_id > largest_peer_created_stream_id_) { | 665 if (stream_id > largest_peer_created_stream_id_) { |
660 // Check if the new number of available streams would cause the number of | 666 // Check if the new number of available streams would cause the number of |
661 // available streams to exceed the limit. Note that the peer can create | 667 // available streams to exceed the limit. Note that the peer can create |
662 // only alternately-numbered streams. | 668 // only alternately-numbered streams. |
663 size_t additional_available_streams = | 669 size_t additional_available_streams = |
664 (stream_id - largest_peer_created_stream_id_) / 2 - 1; | 670 (stream_id - largest_peer_created_stream_id_) / 2 - 1; |
665 size_t new_num_available_streams = | 671 size_t new_num_available_streams = |
666 GetNumAvailableStreams() + additional_available_streams; | 672 GetNumAvailableStreams() + additional_available_streams; |
667 if (new_num_available_streams > get_max_available_streams()) { | 673 if (new_num_available_streams > get_max_available_streams()) { |
668 DVLOG(1) << "Failed to create a new incoming stream with id:" << stream_id | 674 DVLOG(1) << "Failed to create a new incoming stream with id:" << stream_id |
669 << ". There are already " << GetNumAvailableStreams() | 675 << ". There are already " << GetNumAvailableStreams() |
670 << " streams available, which would become " | 676 << " streams available, which would become " |
671 << new_num_available_streams << ", which exceeds the limit " | 677 << new_num_available_streams << ", which exceeds the limit " |
672 << get_max_available_streams() << "."; | 678 << get_max_available_streams() << "."; |
673 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS); | 679 CloseConnectionWithDetails( |
| 680 QUIC_TOO_MANY_AVAILABLE_STREAMS, |
| 681 base::StringPrintf( |
| 682 "%lu above %lu", |
| 683 static_cast<unsigned long>(new_num_available_streams), |
| 684 static_cast<unsigned long>(get_max_available_streams())) |
| 685 .c_str()); |
674 return nullptr; | 686 return nullptr; |
675 } | 687 } |
676 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; id < stream_id; | 688 for (QuicStreamId id = largest_peer_created_stream_id_ + 2; id < stream_id; |
677 id += 2) { | 689 id += 2) { |
678 available_streams_.insert(id); | 690 available_streams_.insert(id); |
679 } | 691 } |
680 largest_peer_created_stream_id_ = stream_id; | 692 largest_peer_created_stream_id_ = stream_id; |
681 } | 693 } |
682 // Check if the new number of open streams would cause the number of | 694 // Check if the new number of open streams would cause the number of |
683 // open streams to exceed the limit. | 695 // open streams to exceed the limit. |
684 size_t num_current_open_streams = | 696 size_t num_current_open_streams = |
685 FLAGS_quic_distinguish_incoming_outgoing_streams | 697 FLAGS_quic_distinguish_incoming_outgoing_streams |
686 ? GetNumOpenIncomingStreams() | 698 ? GetNumOpenIncomingStreams() |
687 : dynamic_stream_map_.size() - draining_streams_.size() + | 699 : dynamic_stream_map_.size() - draining_streams_.size() + |
688 locally_closed_streams_highest_offset_.size(); | 700 locally_closed_streams_highest_offset_.size(); |
689 if (num_current_open_streams >= get_max_open_streams()) { | 701 if (num_current_open_streams >= get_max_open_streams()) { |
690 if (connection()->version() <= QUIC_VERSION_27) { | 702 if (connection()->version() <= QUIC_VERSION_27) { |
691 CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS); | 703 CloseConnectionWithDetails(QUIC_TOO_MANY_OPEN_STREAMS, |
| 704 "Old style stream rejection"); |
692 } else { | 705 } else { |
693 // Refuse to open the stream. | 706 // Refuse to open the stream. |
694 SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0); | 707 SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0); |
695 } | 708 } |
696 return nullptr; | 709 return nullptr; |
697 } | 710 } |
698 ReliableQuicStream* stream = CreateIncomingDynamicStream(stream_id); | 711 ReliableQuicStream* stream = CreateIncomingDynamicStream(stream_id); |
699 if (stream == nullptr) { | 712 if (stream == nullptr) { |
700 return nullptr; | 713 return nullptr; |
701 } | 714 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 } | 823 } |
811 } | 824 } |
812 return false; | 825 return false; |
813 } | 826 } |
814 | 827 |
815 bool QuicSession::IsIncomingStream(QuicStreamId id) const { | 828 bool QuicSession::IsIncomingStream(QuicStreamId id) const { |
816 return id % 2 != next_outgoing_stream_id_ % 2; | 829 return id % 2 != next_outgoing_stream_id_ % 2; |
817 } | 830 } |
818 | 831 |
819 } // namespace net | 832 } // namespace net |
OLD | NEW |