| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 public: | 52 public: |
| 53 explicit TestCryptoStream(QuicSession* session) | 53 explicit TestCryptoStream(QuicSession* session) |
| 54 : QuicCryptoStream(session) { | 54 : QuicCryptoStream(session) { |
| 55 } | 55 } |
| 56 | 56 |
| 57 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override { | 57 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override { |
| 58 encryption_established_ = true; | 58 encryption_established_ = true; |
| 59 handshake_confirmed_ = true; | 59 handshake_confirmed_ = true; |
| 60 CryptoHandshakeMessage msg; | 60 CryptoHandshakeMessage msg; |
| 61 string error_details; | 61 string error_details; |
| 62 session()->config()->SetInitialFlowControlWindowToSend( | |
| 63 kInitialSessionFlowControlWindowForTest); | |
| 64 session()->config()->SetInitialStreamFlowControlWindowToSend( | 62 session()->config()->SetInitialStreamFlowControlWindowToSend( |
| 65 kInitialStreamFlowControlWindowForTest); | 63 kInitialStreamFlowControlWindowForTest); |
| 66 session()->config()->SetInitialSessionFlowControlWindowToSend( | 64 session()->config()->SetInitialSessionFlowControlWindowToSend( |
| 67 kInitialSessionFlowControlWindowForTest); | 65 kInitialSessionFlowControlWindowForTest); |
| 68 session()->config()->ToHandshakeMessage(&msg); | 66 session()->config()->ToHandshakeMessage(&msg); |
| 69 const QuicErrorCode error = session()->config()->ProcessPeerHello( | 67 const QuicErrorCode error = session()->config()->ProcessPeerHello( |
| 70 msg, CLIENT, &error_details); | 68 msg, CLIENT, &error_details); |
| 71 EXPECT_EQ(QUIC_NO_ERROR, error); | 69 EXPECT_EQ(QUIC_NO_ERROR, error); |
| 72 session()->OnConfigNegotiated(); | 70 session()->OnConfigNegotiated(); |
| 73 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); | 71 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 StrictMock<TestCryptoStream> crypto_stream_; | 179 StrictMock<TestCryptoStream> crypto_stream_; |
| 182 | 180 |
| 183 bool writev_consumes_all_data_; | 181 bool writev_consumes_all_data_; |
| 184 }; | 182 }; |
| 185 | 183 |
| 186 class QuicSessionTest : public ::testing::TestWithParam<QuicVersion> { | 184 class QuicSessionTest : public ::testing::TestWithParam<QuicVersion> { |
| 187 protected: | 185 protected: |
| 188 QuicSessionTest() | 186 QuicSessionTest() |
| 189 : connection_(new MockConnection(true, SupportedVersions(GetParam()))), | 187 : connection_(new MockConnection(true, SupportedVersions(GetParam()))), |
| 190 session_(connection_) { | 188 session_(connection_) { |
| 191 session_.config()->SetInitialFlowControlWindowToSend( | |
| 192 kInitialSessionFlowControlWindowForTest); | |
| 193 session_.config()->SetInitialStreamFlowControlWindowToSend( | 189 session_.config()->SetInitialStreamFlowControlWindowToSend( |
| 194 kInitialStreamFlowControlWindowForTest); | 190 kInitialStreamFlowControlWindowForTest); |
| 195 session_.config()->SetInitialSessionFlowControlWindowToSend( | 191 session_.config()->SetInitialSessionFlowControlWindowToSend( |
| 196 kInitialSessionFlowControlWindowForTest); | 192 kInitialSessionFlowControlWindowForTest); |
| 197 headers_[":host"] = "www.google.com"; | 193 headers_[":host"] = "www.google.com"; |
| 198 headers_[":path"] = "/index.hml"; | 194 headers_[":path"] = "/index.hml"; |
| 199 headers_[":scheme"] = "http"; | 195 headers_[":scheme"] = "http"; |
| 200 headers_["cookie"] = | 196 headers_["cookie"] = |
| 201 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " | 197 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " |
| 202 "__utmc=160408618; " | 198 "__utmc=160408618; " |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 CryptoHandshakeMessage msg; | 650 CryptoHandshakeMessage msg; |
| 655 session_.GetCryptoStream()->OnHandshakeMessage(msg); | 651 session_.GetCryptoStream()->OnHandshakeMessage(msg); |
| 656 | 652 |
| 657 // Stream is now unblocked. | 653 // Stream is now unblocked. |
| 658 EXPECT_FALSE(stream2->flow_controller()->IsBlocked()); | 654 EXPECT_FALSE(stream2->flow_controller()->IsBlocked()); |
| 659 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 655 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 660 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 656 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 661 } | 657 } |
| 662 | 658 |
| 663 TEST_P(QuicSessionTest, HandshakeUnblocksFlowControlBlockedCryptoStream) { | 659 TEST_P(QuicSessionTest, HandshakeUnblocksFlowControlBlockedCryptoStream) { |
| 664 if (version() <= QUIC_VERSION_19) { | |
| 665 return; | |
| 666 } | |
| 667 // Test that if the crypto stream is flow control blocked, then if the SHLO | 660 // Test that if the crypto stream is flow control blocked, then if the SHLO |
| 668 // contains a larger send window offset, the stream becomes unblocked. | 661 // contains a larger send window offset, the stream becomes unblocked. |
| 669 session_.set_writev_consumes_all_data(true); | 662 session_.set_writev_consumes_all_data(true); |
| 670 TestCryptoStream* crypto_stream = session_.GetCryptoStream(); | 663 TestCryptoStream* crypto_stream = session_.GetCryptoStream(); |
| 671 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); | 664 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); |
| 672 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 665 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 673 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 666 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 674 QuicHeadersStream* headers_stream = | 667 QuicHeadersStream* headers_stream = |
| 675 QuicSessionPeer::GetHeadersStream(&session_); | 668 QuicSessionPeer::GetHeadersStream(&session_); |
| 676 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 669 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 702 CryptoHandshakeMessage msg; | 695 CryptoHandshakeMessage msg; |
| 703 session_.GetCryptoStream()->OnHandshakeMessage(msg); | 696 session_.GetCryptoStream()->OnHandshakeMessage(msg); |
| 704 | 697 |
| 705 // Stream is now unblocked and will no longer have buffered data. | 698 // Stream is now unblocked and will no longer have buffered data. |
| 706 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); | 699 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); |
| 707 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 700 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 708 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 701 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 709 } | 702 } |
| 710 | 703 |
| 711 TEST_P(QuicSessionTest, HandshakeUnblocksFlowControlBlockedHeadersStream) { | 704 TEST_P(QuicSessionTest, HandshakeUnblocksFlowControlBlockedHeadersStream) { |
| 712 if (version() <= QUIC_VERSION_19) { | |
| 713 return; | |
| 714 } | |
| 715 // Test that if the header stream is flow control blocked, then if the SHLO | 705 // Test that if the header stream is flow control blocked, then if the SHLO |
| 716 // contains a larger send window offset, the stream becomes unblocked. | 706 // contains a larger send window offset, the stream becomes unblocked. |
| 717 session_.set_writev_consumes_all_data(true); | 707 session_.set_writev_consumes_all_data(true); |
| 718 TestCryptoStream* crypto_stream = session_.GetCryptoStream(); | 708 TestCryptoStream* crypto_stream = session_.GetCryptoStream(); |
| 719 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); | 709 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); |
| 720 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 710 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 721 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 711 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 722 QuicHeadersStream* headers_stream = | 712 QuicHeadersStream* headers_stream = |
| 723 QuicSessionPeer::GetHeadersStream(&session_); | 713 QuicSessionPeer::GetHeadersStream(&session_); |
| 724 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 714 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 752 CryptoHandshakeMessage msg; | 742 CryptoHandshakeMessage msg; |
| 753 session_.GetCryptoStream()->OnHandshakeMessage(msg); | 743 session_.GetCryptoStream()->OnHandshakeMessage(msg); |
| 754 | 744 |
| 755 // Stream is now unblocked and will no longer have buffered data. | 745 // Stream is now unblocked and will no longer have buffered data. |
| 756 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 746 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| 757 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 747 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 758 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 748 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 759 EXPECT_FALSE(headers_stream->HasBufferedData()); | 749 EXPECT_FALSE(headers_stream->HasBufferedData()); |
| 760 } | 750 } |
| 761 | 751 |
| 762 TEST_P(QuicSessionTest, InvalidFlowControlWindowInHandshake) { | |
| 763 // TODO(rjshade): Remove this test when removing QUIC_VERSION_19. | |
| 764 // Test that receipt of an invalid (< default) flow control window from | |
| 765 // the peer results in the connection being torn down. | |
| 766 if (version() > QUIC_VERSION_19) { | |
| 767 return; | |
| 768 } | |
| 769 | |
| 770 uint32 kInvalidWindow = kMinimumFlowControlSendWindow - 1; | |
| 771 QuicConfigPeer::SetReceivedInitialFlowControlWindow(session_.config(), | |
| 772 kInvalidWindow); | |
| 773 | |
| 774 EXPECT_CALL(*connection_, | |
| 775 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)).Times(2); | |
| 776 session_.OnConfigNegotiated(); | |
| 777 } | |
| 778 | |
| 779 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstOutOfOrder) { | 752 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstOutOfOrder) { |
| 780 // Test that when we receive an out of order stream RST we correctly adjust | 753 // Test that when we receive an out of order stream RST we correctly adjust |
| 781 // our connection level flow control receive window. | 754 // our connection level flow control receive window. |
| 782 // On close, the stream should mark as consumed all bytes between the highest | 755 // On close, the stream should mark as consumed all bytes between the highest |
| 783 // byte consumed so far and the final byte offset from the RST frame. | 756 // byte consumed so far and the final byte offset from the RST frame. |
| 784 TestStream* stream = session_.CreateOutgoingDataStream(); | 757 TestStream* stream = session_.CreateOutgoingDataStream(); |
| 785 | 758 |
| 786 const QuicStreamOffset kByteOffset = | 759 const QuicStreamOffset kByteOffset = |
| 787 1 + kInitialSessionFlowControlWindowForTest / 2; | 760 1 + kInitialSessionFlowControlWindowForTest / 2; |
| 788 | 761 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 813 QuicStreamFrame frame(stream->id(), true, kByteOffset, IOVector()); | 786 QuicStreamFrame frame(stream->id(), true, kByteOffset, IOVector()); |
| 814 vector<QuicStreamFrame> frames; | 787 vector<QuicStreamFrame> frames; |
| 815 frames.push_back(frame); | 788 frames.push_back(frame); |
| 816 session_.OnStreamFrames(frames); | 789 session_.OnStreamFrames(frames); |
| 817 session_.PostProcessAfterData(); | 790 session_.PostProcessAfterData(); |
| 818 | 791 |
| 819 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); | 792 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); |
| 820 EXPECT_EQ(kByteOffset, | 793 EXPECT_EQ(kByteOffset, |
| 821 stream->flow_controller()->highest_received_byte_offset()); | 794 stream->flow_controller()->highest_received_byte_offset()); |
| 822 | 795 |
| 823 // We only expect to see a connection WINDOW_UPDATE when talking | |
| 824 // QUIC_VERSION_19, as in this case both stream and session flow control | |
| 825 // windows are the same size. In later versions we will not see a connection | |
| 826 // level WINDOW_UPDATE when exhausting a stream, as the stream flow control | |
| 827 // limit is much lower than the connection flow control limit. | |
| 828 if (version() == QUIC_VERSION_19) { | |
| 829 // Expect no stream WINDOW_UPDATE frames, as stream read side closed. | |
| 830 EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0); | |
| 831 // We do expect a connection level WINDOW_UPDATE when the stream is reset. | |
| 832 EXPECT_CALL(*connection_, | |
| 833 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest + | |
| 834 kByteOffset)).Times(1); | |
| 835 } | |
| 836 | |
| 837 // Reset stream locally. | 796 // Reset stream locally. |
| 838 stream->Reset(QUIC_STREAM_CANCELLED); | 797 stream->Reset(QUIC_STREAM_CANCELLED); |
| 839 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); | 798 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); |
| 840 } | 799 } |
| 841 | 800 |
| 842 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAfterRst) { | 801 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAfterRst) { |
| 843 // Test that when we RST the stream (and tear down stream state), and then | 802 // Test that when we RST the stream (and tear down stream state), and then |
| 844 // receive a FIN from the peer, we correctly adjust our connection level flow | 803 // receive a FIN from the peer, we correctly adjust our connection level flow |
| 845 // control receive window. | 804 // control receive window. |
| 846 | 805 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 | 866 |
| 908 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset, | 867 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset, |
| 909 session_.flow_controller()->bytes_consumed()); | 868 session_.flow_controller()->bytes_consumed()); |
| 910 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset, | 869 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset, |
| 911 session_.flow_controller()->highest_received_byte_offset()); | 870 session_.flow_controller()->highest_received_byte_offset()); |
| 912 } | 871 } |
| 913 | 872 |
| 914 TEST_P(QuicSessionTest, InvalidStreamFlowControlWindowInHandshake) { | 873 TEST_P(QuicSessionTest, InvalidStreamFlowControlWindowInHandshake) { |
| 915 // Test that receipt of an invalid (< default) stream flow control window from | 874 // Test that receipt of an invalid (< default) stream flow control window from |
| 916 // the peer results in the connection being torn down. | 875 // the peer results in the connection being torn down. |
| 917 if (version() <= QUIC_VERSION_19) { | |
| 918 return; | |
| 919 } | |
| 920 | |
| 921 uint32 kInvalidWindow = kMinimumFlowControlSendWindow - 1; | 876 uint32 kInvalidWindow = kMinimumFlowControlSendWindow - 1; |
| 922 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(), | 877 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(), |
| 923 kInvalidWindow); | 878 kInvalidWindow); |
| 924 | 879 |
| 925 EXPECT_CALL(*connection_, | 880 EXPECT_CALL(*connection_, |
| 926 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); | 881 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); |
| 927 session_.OnConfigNegotiated(); | 882 session_.OnConfigNegotiated(); |
| 928 } | 883 } |
| 929 | 884 |
| 930 TEST_P(QuicSessionTest, InvalidSessionFlowControlWindowInHandshake) { | 885 TEST_P(QuicSessionTest, InvalidSessionFlowControlWindowInHandshake) { |
| 931 // Test that receipt of an invalid (< default) session flow control window | 886 // Test that receipt of an invalid (< default) session flow control window |
| 932 // from the peer results in the connection being torn down. | 887 // from the peer results in the connection being torn down. |
| 933 if (version() == QUIC_VERSION_19) { | |
| 934 return; | |
| 935 } | |
| 936 | |
| 937 uint32 kInvalidWindow = kMinimumFlowControlSendWindow - 1; | 888 uint32 kInvalidWindow = kMinimumFlowControlSendWindow - 1; |
| 938 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(), | 889 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(), |
| 939 kInvalidWindow); | 890 kInvalidWindow); |
| 940 | 891 |
| 941 EXPECT_CALL(*connection_, | 892 EXPECT_CALL(*connection_, |
| 942 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); | 893 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); |
| 943 session_.OnConfigNegotiated(); | 894 session_.OnConfigNegotiated(); |
| 944 } | 895 } |
| 945 | 896 |
| 946 TEST_P(QuicSessionTest, FlowControlWithInvalidFinalOffset) { | 897 TEST_P(QuicSessionTest, FlowControlWithInvalidFinalOffset) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 961 | 912 |
| 962 // Check that RST results in connection close. | 913 // Check that RST results in connection close. |
| 963 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | 914 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, |
| 964 kLargeOffset); | 915 kLargeOffset); |
| 965 session_.OnRstStream(rst_frame); | 916 session_.OnRstStream(rst_frame); |
| 966 } | 917 } |
| 967 | 918 |
| 968 TEST_P(QuicSessionTest, WindowUpdateUnblocksHeadersStream) { | 919 TEST_P(QuicSessionTest, WindowUpdateUnblocksHeadersStream) { |
| 969 // Test that a flow control blocked headers stream gets unblocked on recipt of | 920 // Test that a flow control blocked headers stream gets unblocked on recipt of |
| 970 // a WINDOW_UPDATE frame. Regression test for b/17413860. | 921 // a WINDOW_UPDATE frame. Regression test for b/17413860. |
| 971 if (version() < QUIC_VERSION_21) { | |
| 972 return; | |
| 973 } | |
| 974 | 922 |
| 975 // Set the headers stream to be flow control blocked. | 923 // Set the headers stream to be flow control blocked. |
| 976 QuicHeadersStream* headers_stream = | 924 QuicHeadersStream* headers_stream = |
| 977 QuicSessionPeer::GetHeadersStream(&session_); | 925 QuicSessionPeer::GetHeadersStream(&session_); |
| 978 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(), | 926 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(), |
| 979 0); | 927 0); |
| 980 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); | 928 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); |
| 981 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 929 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 982 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); | 930 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); |
| 983 | 931 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 } | 963 } |
| 1016 | 964 |
| 1017 // Called after any new data is received by the session, and triggers the call | 965 // Called after any new data is received by the session, and triggers the call |
| 1018 // to close the connection. | 966 // to close the connection. |
| 1019 session_.PostProcessAfterData(); | 967 session_.PostProcessAfterData(); |
| 1020 } | 968 } |
| 1021 | 969 |
| 1022 } // namespace | 970 } // namespace |
| 1023 } // namespace test | 971 } // namespace test |
| 1024 } // namespace net | 972 } // namespace net |
| OLD | NEW |