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 |