Chromium Code Reviews| 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 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 722 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); | 722 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); |
| 723 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 723 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 724 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 724 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 725 QuicHeadersStream* headers_stream = | 725 QuicHeadersStream* headers_stream = |
| 726 QuicSessionPeer::GetHeadersStream(&session_); | 726 QuicSessionPeer::GetHeadersStream(&session_); |
| 727 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 727 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| 728 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 728 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 729 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 729 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 730 QuicStreamId stream_id = 5; | 730 QuicStreamId stream_id = 5; |
| 731 // Write until the header stream is flow control blocked. | 731 // Write until the header stream is flow control blocked. |
| 732 while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) { | 732 while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2010) { |
| 733 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 733 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 734 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 734 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 735 SpdyHeaderBlock headers; | 735 SpdyHeaderBlock headers; |
| 736 headers["header"] = base::Uint64ToString(base::RandUint64()) + | 736 headers["header"] = base::Uint64ToString(base::RandUint64()) + |
| 737 base::Uint64ToString(base::RandUint64()) + | 737 base::Uint64ToString(base::RandUint64()) + |
| 738 base::Uint64ToString(base::RandUint64()); | 738 base::Uint64ToString(base::RandUint64()); |
| 739 headers_stream->WriteHeaders(stream_id, headers, true, nullptr); | 739 headers_stream->WriteHeaders(stream_id, headers, true, nullptr); |
| 740 stream_id += 2; | 740 stream_id += 2; |
| 741 } | 741 } |
| 742 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); | 742 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked()); |
| 743 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); | 743 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); |
| 744 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 744 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 745 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); | 745 EXPECT_TRUE(session_.IsStreamFlowControlBlocked()); |
| 746 EXPECT_FALSE(session_.HasDataToWrite()); | 746 EXPECT_FALSE(session_.HasDataToWrite()); |
| 747 EXPECT_TRUE(headers_stream->HasBufferedData()); | 747 // TODO(rtenneti): crbug.com/423586 headers_stream->HasBufferedData is flaky. |
| 748 // EXPECT_TRUE(headers_stream->HasBufferedData()); | |
|
ramant (doing other things)
2014/10/20 19:05:06
rjshade@: HandshakeUnblocksFlowControlBlockedHeade
| |
| 748 | 749 |
| 749 // Now complete the crypto handshake, resulting in an increased flow control | 750 // Now complete the crypto handshake, resulting in an increased flow control |
| 750 // send window. | 751 // send window. |
| 751 CryptoHandshakeMessage msg; | 752 CryptoHandshakeMessage msg; |
| 752 session_.GetCryptoStream()->OnHandshakeMessage(msg); | 753 session_.GetCryptoStream()->OnHandshakeMessage(msg); |
| 753 | 754 |
| 754 // Stream is now unblocked and will no longer have buffered data. | 755 // Stream is now unblocked and will no longer have buffered data. |
| 755 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 756 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| 756 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 757 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 757 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 758 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 768 | 769 |
| 769 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; | 770 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; |
| 770 QuicConfigPeer::SetReceivedInitialFlowControlWindow(session_.config(), | 771 QuicConfigPeer::SetReceivedInitialFlowControlWindow(session_.config(), |
| 771 kInvalidWindow); | 772 kInvalidWindow); |
| 772 | 773 |
| 773 EXPECT_CALL(*connection_, | 774 EXPECT_CALL(*connection_, |
| 774 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)).Times(2); | 775 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW)).Times(2); |
| 775 session_.OnConfigNegotiated(); | 776 session_.OnConfigNegotiated(); |
| 776 } | 777 } |
| 777 | 778 |
| 779 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstOutOfOrder) { | |
| 780 // Test that when we receive an out of order stream RST we correctly adjust | |
| 781 // our connection level flow control receive window. | |
| 782 // 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. | |
| 784 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 785 | |
| 786 const QuicStreamOffset kByteOffset = | |
| 787 1 + kInitialSessionFlowControlWindowForTest / 2; | |
| 788 | |
| 789 // Expect no stream WINDOW_UPDATE frames, as stream read side closed. | |
| 790 EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0); | |
| 791 // We do expect a connection level WINDOW_UPDATE when the stream is reset. | |
| 792 EXPECT_CALL(*connection_, | |
| 793 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest + | |
| 794 kByteOffset)).Times(1); | |
| 795 | |
| 796 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | |
| 797 kByteOffset); | |
| 798 session_.OnRstStream(rst_frame); | |
| 799 session_.PostProcessAfterData(); | |
| 800 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); | |
| 801 } | |
| 802 | |
| 803 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAndLocalReset) { | |
| 804 // Test the situation where we receive a FIN on a stream, and before we fully | |
| 805 // consume all the data from the sequencer buffer we locally RST the stream. | |
| 806 // The bytes between highest consumed byte, and the final byte offset that we | |
| 807 // determined when the FIN arrived, should be marked as consumed at the | |
| 808 // connection level flow controller when the stream is reset. | |
| 809 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 810 | |
| 811 const QuicStreamOffset kByteOffset = | |
| 812 1 + kInitialSessionFlowControlWindowForTest / 2; | |
| 813 QuicStreamFrame frame(stream->id(), true, kByteOffset, IOVector()); | |
| 814 vector<QuicStreamFrame> frames; | |
| 815 frames.push_back(frame); | |
| 816 session_.OnStreamFrames(frames); | |
| 817 session_.PostProcessAfterData(); | |
| 818 | |
| 819 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); | |
| 820 EXPECT_EQ(kByteOffset, | |
| 821 stream->flow_controller()->highest_received_byte_offset()); | |
| 822 | |
| 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. | |
| 838 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 839 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); | |
| 840 } | |
| 841 | |
| 842 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAfterRst) { | |
| 843 // 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 | |
| 845 // control receive window. | |
| 846 | |
| 847 // Connection starts with some non-zero highest received byte offset, | |
| 848 // due to other active streams. | |
| 849 const uint64 kInitialConnectionBytesConsumed = 567; | |
| 850 const uint64 kInitialConnectionHighestReceivedOffset = 1234; | |
| 851 EXPECT_LT(kInitialConnectionBytesConsumed, | |
| 852 kInitialConnectionHighestReceivedOffset); | |
| 853 session_.flow_controller()->UpdateHighestReceivedOffset( | |
| 854 kInitialConnectionHighestReceivedOffset); | |
| 855 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed); | |
| 856 | |
| 857 // Reset our stream: this results in the stream being closed locally. | |
| 858 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 859 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 860 | |
| 861 // Now receive a response from the peer with a FIN. We should handle this by | |
| 862 // adjusting the connection level flow control receive window to take into | |
| 863 // account the total number of bytes sent by the peer. | |
| 864 const QuicStreamOffset kByteOffset = 5678; | |
| 865 string body = "hello"; | |
| 866 IOVector data = MakeIOVector(body); | |
| 867 QuicStreamFrame frame(stream->id(), true, kByteOffset, data); | |
| 868 vector<QuicStreamFrame> frames; | |
| 869 frames.push_back(frame); | |
| 870 session_.OnStreamFrames(frames); | |
| 871 | |
| 872 QuicStreamOffset total_stream_bytes_sent_by_peer = | |
| 873 kByteOffset + body.length(); | |
| 874 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer, | |
| 875 session_.flow_controller()->bytes_consumed()); | |
| 876 EXPECT_EQ( | |
| 877 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer, | |
| 878 session_.flow_controller()->highest_received_byte_offset()); | |
| 879 } | |
| 880 | |
| 881 TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstAfterRst) { | |
| 882 // Test that when we RST the stream (and tear down stream state), and then | |
| 883 // receive a RST from the peer, we correctly adjust our connection level flow | |
| 884 // control receive window. | |
| 885 | |
| 886 // Connection starts with some non-zero highest received byte offset, | |
| 887 // due to other active streams. | |
| 888 const uint64 kInitialConnectionBytesConsumed = 567; | |
| 889 const uint64 kInitialConnectionHighestReceivedOffset = 1234; | |
| 890 EXPECT_LT(kInitialConnectionBytesConsumed, | |
| 891 kInitialConnectionHighestReceivedOffset); | |
| 892 session_.flow_controller()->UpdateHighestReceivedOffset( | |
| 893 kInitialConnectionHighestReceivedOffset); | |
| 894 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed); | |
| 895 | |
| 896 // Reset our stream: this results in the stream being closed locally. | |
| 897 TestStream* stream = session_.CreateOutgoingDataStream(); | |
| 898 stream->Reset(QUIC_STREAM_CANCELLED); | |
| 899 | |
| 900 // Now receive a RST from the peer. We should handle this by adjusting the | |
| 901 // connection level flow control receive window to take into account the total | |
| 902 // number of bytes sent by the peer. | |
| 903 const QuicStreamOffset kByteOffset = 5678; | |
| 904 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED, | |
| 905 kByteOffset); | |
| 906 session_.OnRstStream(rst_frame); | |
| 907 | |
| 908 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset, | |
| 909 session_.flow_controller()->bytes_consumed()); | |
| 910 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset, | |
| 911 session_.flow_controller()->highest_received_byte_offset()); | |
| 912 } | |
| 913 | |
| 778 TEST_P(QuicSessionTest, InvalidStreamFlowControlWindowInHandshake) { | 914 TEST_P(QuicSessionTest, InvalidStreamFlowControlWindowInHandshake) { |
| 779 // Test that receipt of an invalid (< default) stream flow control window from | 915 // Test that receipt of an invalid (< default) stream flow control window from |
| 780 // the peer results in the connection being torn down. | 916 // the peer results in the connection being torn down. |
| 781 if (version() <= QUIC_VERSION_19) { | 917 if (version() <= QUIC_VERSION_19) { |
| 782 return; | 918 return; |
| 783 } | 919 } |
| 784 | 920 |
| 785 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; | 921 uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1; |
| 786 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(), | 922 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(), |
| 787 kInvalidWindow); | 923 kInvalidWindow); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 QuicWindowUpdateFrame window_update_frame(headers_stream->id(), | 985 QuicWindowUpdateFrame window_update_frame(headers_stream->id(), |
| 850 2 * kDefaultFlowControlSendWindow); | 986 2 * kDefaultFlowControlSendWindow); |
| 851 vector<QuicWindowUpdateFrame> frames; | 987 vector<QuicWindowUpdateFrame> frames; |
| 852 frames.push_back(window_update_frame); | 988 frames.push_back(window_update_frame); |
| 853 session_.OnWindowUpdateFrames(frames); | 989 session_.OnWindowUpdateFrames(frames); |
| 854 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 990 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
| 855 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 991 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
| 856 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 992 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
| 857 } | 993 } |
| 858 | 994 |
| 995 TEST_P(QuicSessionTest, TooManyUnfinishedStreamsCauseConnectionClose) { | |
| 996 // If a buggy/malicious peer creates too many streams that are not ended with | |
| 997 // a FIN or RST then we send a connection close. | |
| 998 FLAGS_close_quic_connection_unfinished_streams_2 = true; | |
| 999 | |
| 1000 EXPECT_CALL(*connection_, | |
| 1001 SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS)).Times(1); | |
| 1002 | |
| 1003 const int kMaxStreams = 5; | |
| 1004 QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams); | |
| 1005 | |
| 1006 // Create kMaxStreams + 1 data streams, and close them all without receiving a | |
| 1007 // FIN or a RST from the client. | |
| 1008 const int kFirstStreamId = kClientDataStreamId1; | |
| 1009 const int kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams + 1; | |
| 1010 for (int i = kFirstStreamId; i < kFinalStreamId; i += 2) { | |
| 1011 QuicStreamFrame data1(i, false, 0, MakeIOVector("HT")); | |
| 1012 vector<QuicStreamFrame> frames; | |
| 1013 frames.push_back(data1); | |
| 1014 session_.OnStreamFrames(frames); | |
| 1015 EXPECT_EQ(1u, session_.GetNumOpenStreams()); | |
| 1016 session_.CloseStream(i); | |
| 1017 } | |
| 1018 | |
| 1019 // Called after any new data is received by the session, and triggers the call | |
| 1020 // to close the connection. | |
| 1021 session_.PostProcessAfterData(); | |
| 1022 } | |
| 1023 | |
| 859 } // namespace | 1024 } // namespace |
| 860 } // namespace test | 1025 } // namespace test |
| 861 } // namespace net | 1026 } // namespace net |
| OLD | NEW |