1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/tools/quic/quic_server_session.h" 6 7 #include "net/quic/crypto/quic_crypto_server_config.h" 8 #include "net/quic/crypto/quic_random.h" 9 #include "net/quic/quic_connection.h" 10 #include "net/quic/quic_utils.h" 11 #include "net/quic/test_tools/quic_connection_peer.h" 12 #include "net/quic/test_tools/quic_data_stream_peer.h" 13 #include "net/quic/test_tools/quic_test_utils.h" 14 #include "net/tools/quic/quic_spdy_server_stream.h" 15 #include "net/tools/quic/test_tools/quic_test_utils.h" 16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 using __gnu_cxx::vector; 20 using net::test::MockConnection; 21 using net::test::QuicConnectionPeer; 22 using net::test::QuicDataStreamPeer; 23 using net::test::SupportedVersions; 24 using net::test::kClientDataStreamId1; 25 using net::test::kClientDataStreamId2; 26 using net::test::kClientDataStreamId3; 27 using net::test::kClientDataStreamId4; 28 using testing::StrictMock; 29 using testing::_; 30 31 namespace net { 32 namespace tools { 33 namespace test { 34 35 class QuicServerSessionPeer { 36 public: 37 static QuicDataStream* GetIncomingDataStream( 38 QuicServerSession* s, QuicStreamId id) { 39 return s->GetIncomingDataStream(id); 40 } 41 static QuicDataStream* GetDataStream(QuicServerSession* s, QuicStreamId id) { 42 return s->GetDataStream(id); 43 } 44 }; 45 46 namespace { 47 48 class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> { 49 protected: 50 QuicServerSessionTest() 51 : crypto_config_(QuicCryptoServerConfig::TESTING, 52 QuicRandom::GetInstance()) { 53 config_.SetDefaults(); 54 config_.set_max_streams_per_connection(3, 3); 55 config_.SetInitialFlowControlWindowToSend( 56 kInitialSessionFlowControlWindowForTest); 57 config_.SetInitialStreamFlowControlWindowToSend( 58 kInitialStreamFlowControlWindowForTest); 59 config_.SetInitialSessionFlowControlWindowToSend( 60 kInitialSessionFlowControlWindowForTest); 61 62 connection_ = 63 new StrictMock<MockConnection>(true, SupportedVersions(GetParam())); 64 session_.reset(new QuicServerSession(config_, connection_, &owner_)); 65 session_->InitializeSession(crypto_config_); 66 visitor_ = QuicConnectionPeer::GetVisitor(connection_); 67 } 68 69 QuicVersion version() const { return connection_->version(); } 70 71 StrictMock<MockQuicServerSessionVisitor> owner_; 72 StrictMock<MockConnection>* connection_; 73 QuicConfig config_; 74 QuicCryptoServerConfig crypto_config_; 75 scoped_ptr<QuicServerSession> session_; 76 QuicConnectionVisitorInterface* visitor_; 77 }; 78 79 INSTANTIATE_TEST_CASE_P(Tests, QuicServerSessionTest, 80 ::testing::ValuesIn(QuicSupportedVersions())); 81 82 TEST_P(QuicServerSessionTest, CloseStreamDueToReset) { 83 // Open a stream, then reset it. 84 // Send two bytes of payload to open it. 85 QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT")); 86 vector<QuicStreamFrame> frames; 87 frames.push_back(data1); 88 session_->OnStreamFrames(frames); 89 EXPECT_EQ(1u, session_->GetNumOpenStreams()); 90 91 // Send a reset (and expect the peer to send a RST in response). 92 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); 93 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, 94 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0)); 95 visitor_->OnRstStream(rst1); 96 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 97 98 // Send the same two bytes of payload in a new packet. 99 visitor_->OnStreamFrames(frames); 100 101 // The stream should not be re-opened. 102 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 103 EXPECT_TRUE(connection_->connected()); 104 } 105 106 TEST_P(QuicServerSessionTest, NeverOpenStreamDueToReset) { 107 // Send a reset (and expect the peer to send a RST in response). 108 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); 109 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, 110 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0)); 111 visitor_->OnRstStream(rst1); 112 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 113 114 // Send two bytes of payload. 115 QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT")); 116 vector<QuicStreamFrame> frames; 117 frames.push_back(data1); 118 visitor_->OnStreamFrames(frames); 119 120 // The stream should never be opened, now that the reset is received. 121 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 122 EXPECT_TRUE(connection_->connected()); 123 } 124 125 TEST_P(QuicServerSessionTest, AcceptClosedStream) { 126 vector<QuicStreamFrame> frames; 127 // Send (empty) compressed headers followed by two bytes of data. 128 frames.push_back(QuicStreamFrame(kClientDataStreamId1, false, 0, 129 MakeIOVector("\1\0\0\0\0\0\0\0HT"))); 130 frames.push_back(QuicStreamFrame(kClientDataStreamId2, false, 0, 131 MakeIOVector("\2\0\0\0\0\0\0\0HT"))); 132 visitor_->OnStreamFrames(frames); 133 EXPECT_EQ(2u, session_->GetNumOpenStreams()); 134 135 // Send a reset (and expect the peer to send a RST in response). 136 QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); 137 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, 138 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0)); 139 visitor_->OnRstStream(rst); 140 141 // If we were tracking, we'd probably want to reject this because it's data 142 // past the reset point of stream 3. As it's a closed stream we just drop the 143 // data on the floor, but accept the packet because it has data for stream 5. 144 frames.clear(); 145 frames.push_back( 146 QuicStreamFrame(kClientDataStreamId1, false, 2, MakeIOVector("TP"))); 147 frames.push_back( 148 QuicStreamFrame(kClientDataStreamId2, false, 2, MakeIOVector("TP"))); 149 visitor_->OnStreamFrames(frames); 150 // The stream should never be opened, now that the reset is received. 151 EXPECT_EQ(1u, session_->GetNumOpenStreams()); 152 EXPECT_TRUE(connection_->connected()); 153 } 154 155 TEST_P(QuicServerSessionTest, MaxNumConnections) { 156 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 157 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream( 158 session_.get(), kClientDataStreamId1)); 159 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream( 160 session_.get(), kClientDataStreamId2)); 161 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream( 162 session_.get(), kClientDataStreamId3)); 163 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); 164 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream( 165 session_.get(), kClientDataStreamId4)); 166 } 167 168 TEST_P(QuicServerSessionTest, MaxNumConnectionsImplicit) { 169 EXPECT_EQ(0u, session_->GetNumOpenStreams()); 170 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream( 171 session_.get(), kClientDataStreamId1)); 172 // Implicitly opens two more streams. 173 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); 174 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream( 175 session_.get(), kClientDataStreamId4)); 176 } 177 178 TEST_P(QuicServerSessionTest, GetEvenIncomingError) { 179 // Incoming streams on the server session must be odd. 180 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID)); 181 EXPECT_EQ(NULL, 182 QuicServerSessionPeer::GetIncomingDataStream(session_.get(), 4)); 183 } 184 185 } // namespace 186 } // namespace test 187 } // namespace tools 188 } // namespace net 189