| 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 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 CloseStream(stream6->id()); | 522 CloseStream(stream6->id()); |
| 523 | 523 |
| 524 InSequence s; | 524 InSequence s; |
| 525 EXPECT_CALL(*stream2, OnCanWrite()); | 525 EXPECT_CALL(*stream2, OnCanWrite()); |
| 526 EXPECT_CALL(*stream4, OnCanWrite()); | 526 EXPECT_CALL(*stream4, OnCanWrite()); |
| 527 session_.OnCanWrite(); | 527 session_.OnCanWrite(); |
| 528 EXPECT_FALSE(session_.WillingAndAbleToWrite()); | 528 EXPECT_FALSE(session_.WillingAndAbleToWrite()); |
| 529 } | 529 } |
| 530 | 530 |
| 531 TEST_P(QuicSessionTest, OnCanWriteLimitsNumWritesIfFlowControlBlocked) { | 531 TEST_P(QuicSessionTest, OnCanWriteLimitsNumWritesIfFlowControlBlocked) { |
| 532 if (version() < QUIC_VERSION_19) { | |
| 533 return; | |
| 534 } | |
| 535 | |
| 536 // Ensure connection level flow control blockage. | 532 // Ensure connection level flow control blockage. |
| 537 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0); | 533 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0); |
| 538 EXPECT_TRUE(session_.flow_controller()->IsBlocked()); | 534 EXPECT_TRUE(session_.flow_controller()->IsBlocked()); |
| 539 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked()); | 535 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked()); |
| 540 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 536 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 541 | 537 |
| 542 // Mark the crypto and headers streams as write blocked, we expect them to be | 538 // Mark the crypto and headers streams as write blocked, we expect them to be |
| 543 // allowed to write later. | 539 // allowed to write later. |
| 544 session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority); | 540 session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority); |
| 545 session_.MarkWriteBlocked(kHeadersStreamId, kHighestPriority); | 541 session_.MarkWriteBlocked(kHeadersStreamId, kHighestPriority); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 kInvalidWindow); | 786 kInvalidWindow); |
| 791 | 787 |
| 792 EXPECT_CALL(*connection_, | 788 EXPECT_CALL(*connection_, |
| 793 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); | 789 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); |
| 794 session_.OnConfigNegotiated(); | 790 session_.OnConfigNegotiated(); |
| 795 } | 791 } |
| 796 | 792 |
| 797 TEST_P(QuicSessionTest, InvalidSessionFlowControlWindowInHandshake) { | 793 TEST_P(QuicSessionTest, InvalidSessionFlowControlWindowInHandshake) { |
| 798 // Test that receipt of an invalid (< default) session flow control window | 794 // Test that receipt of an invalid (< default) session flow control window |
| 799 // from the peer results in the connection being torn down. | 795 // from the peer results in the connection being torn down. |
| 800 if (version() <= QUIC_VERSION_19) { | 796 if (version() == QUIC_VERSION_19) { |
| 801 return; | 797 return; |
| 802 } | 798 } |
| 803 | 799 |
| 804 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; | 800 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; |
| 805 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(), | 801 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(), |
| 806 kInvalidWindow); | 802 kInvalidWindow); |
| 807 | 803 |
| 808 EXPECT_CALL(*connection_, | 804 EXPECT_CALL(*connection_, |
| 809 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); | 805 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)); |
| 810 session_.OnConfigNegotiated(); | 806 session_.OnConfigNegotiated(); |
| 811 } | 807 } |
| 812 | 808 |
| 813 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstOutOfOrder) { | |
| 814 if (version() < QUIC_VERSION_19) { | |
| 815 return; | |
| 816 } | |
| 817 | |
| 818 // Test that when we receive an out of order stream RST we correctly adjust | |
| 819 // our connection level flow control receive window. | |
| 820 // On close, the stream should mark as consumed all bytes between the highest | |
| 821 // byte consumed so far and the final byte offset from the RST frame. | |
| 822 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 823 | |
| 824 const QuicStreamOffset kByteOffset = | |
| 825 1 + kInitialSessionFlowControlWindowForTest / 2; | |
| 826 | |
| 827 // Expect no stream WINDOW_UPDATE frames, as stream read side closed. | |
| 828 EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0); | |
| 829 // We do expect a connection level WINDOW_UPDATE when the stream is reset. | |
| 830 EXPECT_CALL(*connection_, | |
| 831 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest + | |
| 832 kByteOffset)).Times(1); | |
| 833 | |
| 834 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | |
| 835 kByteOffset); | |
| 836 session_.OnRstStream(rst_frame); | |
| 837 session_.PostProcessAfterData(); | |
| 838 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); | |
| 839 } | |
| 840 | |
| 841 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAndLocalReset) { | |
| 842 if (version() < QUIC_VERSION_19) { | |
| 843 return; | |
| 844 } | |
| 845 | |
| 846 // Test the situation where we receive a FIN on a stream, and before we fully | |
| 847 // consume all the data from the sequencer buffer we locally RST the stream. | |
| 848 // The bytes between highest consumed byte, and the final byte offset that we | |
| 849 // determined when the FIN arrived, should be marked as consumed at the | |
| 850 // connection level flow controller when the stream is reset. | |
| 851 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 852 | |
| 853 const QuicStreamOffset kByteOffset = | |
| 854 1 + kInitialSessionFlowControlWindowForTest / 2; | |
| 855 QuicStreamFrame frame(stream->id(), true, kByteOffset, IOVector()); | |
| 856 vector<QuicStreamFrame> frames; | |
| 857 frames.push_back(frame); | |
| 858 session_.OnStreamFrames(frames); | |
| 859 session_.PostProcessAfterData(); | |
| 860 | |
| 861 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); | |
| 862 EXPECT_EQ(kByteOffset, | |
| 863 stream->flow_controller()->highest_received_byte_offset()); | |
| 864 | |
| 865 // We only expect to see a connection WINDOW_UPDATE when talking | |
| 866 // QUIC_VERSION_19, as in this case both stream and session flow control | |
| 867 // windows are the same size. In later versions we will not see a connection | |
| 868 // level WINDOW_UPDATE when exhausting a stream, as the stream flow control | |
| 869 // limit is much lower than the connection flow control limit. | |
| 870 if (version() == QUIC_VERSION_19) { | |
| 871 // Expect no stream WINDOW_UPDATE frames, as stream read side closed. | |
| 872 EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0); | |
| 873 // We do expect a connection level WINDOW_UPDATE when the stream is reset. | |
| 874 EXPECT_CALL(*connection_, | |
| 875 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest + | |
| 876 kByteOffset)).Times(1); | |
| 877 } | |
| 878 | |
| 879 // Reset stream locally. | |
| 880 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 881 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); | |
| 882 } | |
| 883 | |
| 884 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAfterRst) { | |
| 885 // Test that when we RST the stream (and tear down stream state), and then | |
| 886 // receive a FIN from the peer, we correctly adjust our connection level flow | |
| 887 // control receive window. | |
| 888 if (version() < QUIC_VERSION_19) { | |
| 889 return; | |
| 890 } | |
| 891 | |
| 892 // Connection starts with some non-zero highest received byte offset, | |
| 893 // due to other active streams. | |
| 894 const uint64 kInitialConnectionBytesConsumed = 567; | |
| 895 const uint64 kInitialConnectionHighestReceivedOffset = 1234; | |
| 896 EXPECT_LT(kInitialConnectionBytesConsumed, | |
| 897 kInitialConnectionHighestReceivedOffset); | |
| 898 session_.flow_controller()->UpdateHighestReceivedOffset( | |
| 899 kInitialConnectionHighestReceivedOffset); | |
| 900 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed); | |
| 901 | |
| 902 // Reset our stream: this results in the stream being closed locally. | |
| 903 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 904 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 905 | |
| 906 // Now receive a response from the peer with a FIN. We should handle this by | |
| 907 // adjusting the connection level flow control receive window to take into | |
| 908 // account the total number of bytes sent by the peer. | |
| 909 const QuicStreamOffset kByteOffset = 5678; | |
| 910 string body = "hello"; | |
| 911 IOVector data = MakeIOVector(body); | |
| 912 QuicStreamFrame frame(stream->id(), true, kByteOffset, data); | |
| 913 vector<QuicStreamFrame> frames; | |
| 914 frames.push_back(frame); | |
| 915 session_.OnStreamFrames(frames); | |
| 916 | |
| 917 QuicStreamOffset total_stream_bytes_sent_by_peer = | |
| 918 kByteOffset + body.length(); | |
| 919 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer, | |
| 920 session_.flow_controller()->bytes_consumed()); | |
| 921 EXPECT_EQ( | |
| 922 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer, | |
| 923 session_.flow_controller()->highest_received_byte_offset()); | |
| 924 } | |
| 925 | |
| 926 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstAfterRst) { | |
| 927 // Test that when we RST the stream (and tear down stream state), and then | |
| 928 // receive a RST from the peer, we correctly adjust our connection level flow | |
| 929 // control receive window. | |
| 930 if (version() < QUIC_VERSION_19) { | |
| 931 return; | |
| 932 } | |
| 933 | |
| 934 // Connection starts with some non-zero highest received byte offset, | |
| 935 // due to other active streams. | |
| 936 const uint64 kInitialConnectionBytesConsumed = 567; | |
| 937 const uint64 kInitialConnectionHighestReceivedOffset = 1234; | |
| 938 EXPECT_LT(kInitialConnectionBytesConsumed, | |
| 939 kInitialConnectionHighestReceivedOffset); | |
| 940 session_.flow_controller()->UpdateHighestReceivedOffset( | |
| 941 kInitialConnectionHighestReceivedOffset); | |
| 942 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed); | |
| 943 | |
| 944 // Reset our stream: this results in the stream being closed locally. | |
| 945 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 946 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 947 | |
| 948 // Now receive a RST from the peer. We should handle this by adjusting the | |
| 949 // connection level flow control receive window to take into account the total | |
| 950 // number of bytes sent by the peer. | |
| 951 const QuicStreamOffset kByteOffset = 5678; | |
| 952 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | |
| 953 kByteOffset); | |
| 954 session_.OnRstStream(rst_frame); | |
| 955 | |
| 956 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset, | |
| 957 session_.flow_controller()->bytes_consumed()); | |
| 958 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset, | |
| 959 session_.flow_controller()->highest_received_byte_offset()); | |
| 960 } | |
| 961 | |
| 962 TEST_P(QuicSessionTest, FlowControlWithInvalidFinalOffset) { | 809 TEST_P(QuicSessionTest, FlowControlWithInvalidFinalOffset) { |
| 963 // Test that if we receive a stream RST with a highest byte offset that | 810 // Test that if we receive a stream RST with a highest byte offset that |
| 964 // violates flow control, that we close the connection. | 811 // violates flow control, that we close the connection. |
| 965 const uint64 kLargeOffset = kInitialSessionFlowControlWindowForTest + 1; | 812 const uint64 kLargeOffset = kInitialSessionFlowControlWindowForTest + 1; |
| 966 EXPECT_CALL(*connection_, | 813 EXPECT_CALL(*connection_, |
| 967 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)) | 814 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)) |
| 968 .Times(2); | 815 .Times(2); |
| 969 | 816 |
| 970 // Check that stream frame + FIN results in connection close. | 817 // Check that stream frame + FIN results in connection close. |
| 971 TestStream* stream = session_.CreateOutgoingDataStream(); | 818 TestStream* stream = session_.CreateOutgoingDataStream(); |
| 972 stream->Reset(QUIC_STREAM_CANCELLED); | 819 stream->Reset(QUIC_STREAM_CANCELLED); |
| 973 QuicStreamFrame frame(stream->id(), true, kLargeOffset, IOVector()); | 820 QuicStreamFrame frame(stream->id(), true, kLargeOffset, IOVector()); |
| 974 vector<QuicStreamFrame> frames; | 821 vector<QuicStreamFrame> frames; |
| 975 frames.push_back(frame); | 822 frames.push_back(frame); |
| 976 session_.OnStreamFrames(frames); | 823 session_.OnStreamFrames(frames); |
| 977 | 824 |
| 978 // Check that RST results in connection close. | 825 // Check that RST results in connection close. |
| 979 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | 826 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, |
| 980 kLargeOffset); | 827 kLargeOffset); |
| 981 session_.OnRstStream(rst_frame); | 828 session_.OnRstStream(rst_frame); |
| 982 } | 829 } |
| 983 | 830 |
| 984 TEST_P(QuicSessionTest, VersionNegotiationDisablesFlowControl) { | |
| 985 if (version() < QUIC_VERSION_19) { | |
| 986 return; | |
| 987 } | |
| 988 | |
| 989 // Test that after successful version negotiation, flow control is disabled | |
| 990 // appropriately at both the connection and stream level. | |
| 991 | |
| 992 // Initially both stream and connection flow control are enabled. | |
| 993 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 994 EXPECT_TRUE(stream->flow_controller()->IsEnabled()); | |
| 995 EXPECT_TRUE(session_.flow_controller()->IsEnabled()); | |
| 996 | |
| 997 // Version 18 implies that stream flow control is enabled, but connection | |
| 998 // level is disabled. | |
| 999 session_.OnSuccessfulVersionNegotiation(QUIC_VERSION_18); | |
| 1000 EXPECT_FALSE(session_.flow_controller()->IsEnabled()); | |
| 1001 EXPECT_TRUE(stream->flow_controller()->IsEnabled()); | |
| 1002 } | |
| 1003 | |
| 1004 TEST_P(QuicSessionTest, WindowUpdateUnblocksHeadersStream) { | 831 TEST_P(QuicSessionTest, WindowUpdateUnblocksHeadersStream) { |
| 1005 // Test that a flow control blocked headers stream gets unblocked on recipt of | 832 // Test that a flow control blocked headers stream gets unblocked on recipt of |
| 1006 // a WINDOW_UPDATE frame. Regression test for b/17413860. | 833 // a WINDOW_UPDATE frame. Regression test for b/17413860. |
| 1007 if (version() < QUIC_VERSION_21) { | 834 if (version() < QUIC_VERSION_21) { |
| 1008 return; | 835 return; |
| 1009 } | 836 } |
| 1010 | 837 |
| 1011 // Set the headers stream to be flow control blocked. | 838 // Set the headers stream to be flow control blocked. |
| 1012 QuicHeadersStream* headers_stream = | 839 QuicHeadersStream* headers_stream = |
| 1013 QuicSessionPeer::GetHeadersStream(&session_); | 840 QuicSessionPeer::GetHeadersStream(&session_); |
| 1014 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(), | 841 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(), |
| 1015 0); | 842 0); |
| 1016 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); | 843 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); |
| 1017 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 844 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 1018 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); | 845 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); |
| 1019 | 846 |
| 1020 // Unblock the headers stream by supplying a WINDOW_UPDATE. | 847 // Unblock the headers stream by supplying a WINDOW_UPDATE. |
| 1021 QuicWindowUpdateFrame window_update_frame(headers_stream->id(), | 848 QuicWindowUpdateFrame window_update_frame(headers_stream->id(), |
| 1022 2 * kDefaultFlowControlSendWindow); | 849 2 * kDefaultFlowControlSendWindow); |
| 1023 vector<QuicWindowUpdateFrame> frames; | 850 vector<QuicWindowUpdateFrame> frames; |
| 1024 frames.push_back(window_update_frame); | 851 frames.push_back(window_update_frame); |
| 1025 session_.OnWindowUpdateFrames(frames); | 852 session_.OnWindowUpdateFrames(frames); |
| 1026 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 853 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| 1027 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 854 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 1028 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 855 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 1029 } | 856 } |
| 1030 | 857 |
| 1031 TEST_P(QuicSessionTest, TooManyUnfinishedStreamsCauseConnectionClose) { | |
| 1032 if (version() < QUIC_VERSION_18) { | |
| 1033 return; | |
| 1034 } | |
| 1035 // If a buggy/malicious peer creates too many streams that are not ended with | |
| 1036 // a FIN or RST then we send a connection close. | |
| 1037 ValueRestore<bool> old_flag(&FLAGS_close_quic_connection_unfinished_streams_2, | |
| 1038 true); | |
| 1039 | |
| 1040 EXPECT_CALL(*connection_, | |
| 1041 SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS)).Times(1); | |
| 1042 | |
| 1043 const int kMaxStreams = 5; | |
| 1044 QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams); | |
| 1045 | |
| 1046 // Create kMaxStreams + 1 data streams, and close them all without receiving a | |
| 1047 // FIN or a RST from the client. | |
| 1048 const int kFirstStreamId = kClientDataStreamId1; | |
| 1049 const int kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams + 1; | |
| 1050 for (int i = kFirstStreamId; i < kFinalStreamId; i += 2) { | |
| 1051 QuicStreamFrame data1(i, false, 0, MakeIOVector("HT")); | |
| 1052 vector<QuicStreamFrame> frames; | |
| 1053 frames.push_back(data1); | |
| 1054 session_.OnStreamFrames(frames); | |
| 1055 EXPECT_EQ(1u, session_.GetNumOpenStreams()); | |
| 1056 session_.CloseStream(i); | |
| 1057 } | |
| 1058 | |
| 1059 // Called after any new data is received by the session, and triggers the call | |
| 1060 // to close the connection. | |
| 1061 session_.PostProcessAfterData(); | |
| 1062 } | |
| 1063 | |
| 1064 } // namespace | 858 } // namespace |
| 1065 } // namespace test | 859 } // namespace test |
| 1066 } // namespace net | 860 } // namespace net |
| OLD | NEW |