| 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/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| 11 #include "net/quic/crypto/crypto_handshake.h" | 11 #include "net/quic/crypto/crypto_handshake.h" |
| 12 #include "net/quic/quic_connection.h" | 12 #include "net/quic/quic_connection.h" |
| 13 #include "net/quic/quic_protocol.h" | 13 #include "net/quic/quic_protocol.h" |
| 14 #include "net/quic/test_tools/quic_connection_peer.h" | 14 #include "net/quic/test_tools/quic_connection_peer.h" |
| 15 #include "net/quic/test_tools/quic_test_utils.h" | 15 #include "net/quic/test_tools/quic_test_utils.h" |
| 16 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
| 16 #include "net/spdy/spdy_framer.h" | 17 #include "net/spdy/spdy_framer.h" |
| 17 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 20 |
| 20 using base::hash_map; | 21 using base::hash_map; |
| 21 using std::set; | 22 using std::set; |
| 22 using std::vector; | 23 using std::vector; |
| 23 using testing::_; | 24 using testing::_; |
| 24 using testing::InSequence; | 25 using testing::InSequence; |
| 26 using testing::StrictMock; |
| 25 | 27 |
| 26 namespace net { | 28 namespace net { |
| 27 namespace test { | 29 namespace test { |
| 28 namespace { | 30 namespace { |
| 29 | 31 |
| 30 class TestCryptoStream : public QuicCryptoStream { | 32 class TestCryptoStream : public QuicCryptoStream { |
| 31 public: | 33 public: |
| 32 explicit TestCryptoStream(QuicSession* session) | 34 explicit TestCryptoStream(QuicSession* session) |
| 33 : QuicCryptoStream(session) { | 35 : QuicCryptoStream(session) { |
| 34 } | 36 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 | 100 |
| 99 TestCryptoStream crypto_stream_; | 101 TestCryptoStream crypto_stream_; |
| 100 }; | 102 }; |
| 101 | 103 |
| 102 class QuicSessionTest : public ::testing::Test { | 104 class QuicSessionTest : public ::testing::Test { |
| 103 protected: | 105 protected: |
| 104 QuicSessionTest() | 106 QuicSessionTest() |
| 105 : guid_(1), | 107 : guid_(1), |
| 106 connection_(new MockConnection(guid_, IPEndPoint(), false)), | 108 connection_(new MockConnection(guid_, IPEndPoint(), false)), |
| 107 session_(connection_, true) { | 109 session_(connection_, true) { |
| 110 headers_[":host"] = "www.google.com"; |
| 111 headers_[":path"] = "/index.hml"; |
| 112 headers_[":scheme"] = "http"; |
| 113 headers_["cookie"] = |
| 114 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " |
| 115 "__utmc=160408618; " |
| 116 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX" |
| 117 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX" |
| 118 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT" |
| 119 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0" |
| 120 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh" |
| 121 "1zFMi5vzcns38-8_Sns; " |
| 122 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-" |
| 123 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339" |
| 124 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c" |
| 125 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%" |
| 126 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4" |
| 127 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1" |
| 128 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP" |
| 129 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6" |
| 130 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b" |
| 131 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6" |
| 132 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG" |
| 133 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk" |
| 134 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn" |
| 135 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" |
| 136 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; |
| 108 } | 137 } |
| 109 | 138 |
| 110 void CheckClosedStreams() { | 139 void CheckClosedStreams() { |
| 111 for (int i = kCryptoStreamId; i < 100; i++) { | 140 for (int i = kCryptoStreamId; i < 100; i++) { |
| 112 if (closed_streams_.count(i) == 0) { | 141 if (closed_streams_.count(i) == 0) { |
| 113 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i; | 142 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i; |
| 114 } else { | 143 } else { |
| 115 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i; | 144 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i; |
| 116 } | 145 } |
| 117 } | 146 } |
| 118 } | 147 } |
| 119 | 148 |
| 120 void CloseStream(QuicStreamId id) { | 149 void CloseStream(QuicStreamId id) { |
| 121 session_.CloseStream(id); | 150 session_.CloseStream(id); |
| 122 closed_streams_.insert(id); | 151 closed_streams_.insert(id); |
| 123 } | 152 } |
| 124 | 153 |
| 125 QuicGuid guid_; | 154 QuicGuid guid_; |
| 126 MockConnection* connection_; | 155 MockConnection* connection_; |
| 127 TestSession session_; | 156 TestSession session_; |
| 128 set<QuicStreamId> closed_streams_; | 157 set<QuicStreamId> closed_streams_; |
| 158 SpdyHeaderBlock headers_; |
| 129 }; | 159 }; |
| 130 | 160 |
| 131 TEST_F(QuicSessionTest, PeerAddress) { | 161 TEST_F(QuicSessionTest, PeerAddress) { |
| 132 EXPECT_EQ(IPEndPoint(), session_.peer_address()); | 162 EXPECT_EQ(IPEndPoint(), session_.peer_address()); |
| 133 } | 163 } |
| 134 | 164 |
| 135 TEST_F(QuicSessionTest, IsCryptoHandshakeConfirmed) { | 165 TEST_F(QuicSessionTest, IsCryptoHandshakeConfirmed) { |
| 136 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed()); | 166 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed()); |
| 137 CryptoHandshakeMessage message; | 167 CryptoHandshakeMessage message; |
| 138 session_.crypto_stream_.OnHandshakeMessage(message); | 168 session_.crypto_stream_.OnHandshakeMessage(message); |
| 139 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed()); | 169 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed()); |
| 140 } | 170 } |
| 141 | 171 |
| 142 TEST_F(QuicSessionTest, IsClosedStreamDefault) { | 172 TEST_F(QuicSessionTest, IsClosedStreamDefault) { |
| 143 // Ensure that no streams are initially closed. | 173 // Ensure that no streams are initially closed. |
| 144 for (int i = kCryptoStreamId; i < 100; i++) { | 174 for (int i = kCryptoStreamId; i < 100; i++) { |
| 145 EXPECT_FALSE(session_.IsClosedStream(i)); | 175 EXPECT_FALSE(session_.IsClosedStream(i)); |
| 146 } | 176 } |
| 147 } | 177 } |
| 148 | 178 |
| 149 TEST_F(QuicSessionTest, IsClosedStreamLocallyCreated) { | 179 TEST_F(QuicSessionTest, IsClosedStreamLocallyCreated) { |
| 150 TestStream* stream2 = session_.CreateOutgoingReliableStream(); | 180 TestStream* stream2 = session_.CreateOutgoingReliableStream(); |
| 151 EXPECT_EQ(2u, stream2->id()); | 181 EXPECT_EQ(2u, stream2->id()); |
| 182 ReliableQuicStreamPeer::SetHeadersDecompressed(stream2, true); |
| 152 TestStream* stream4 = session_.CreateOutgoingReliableStream(); | 183 TestStream* stream4 = session_.CreateOutgoingReliableStream(); |
| 153 EXPECT_EQ(4u, stream4->id()); | 184 EXPECT_EQ(4u, stream4->id()); |
| 185 ReliableQuicStreamPeer::SetHeadersDecompressed(stream4, true); |
| 154 | 186 |
| 155 CheckClosedStreams(); | 187 CheckClosedStreams(); |
| 156 CloseStream(4); | 188 CloseStream(4); |
| 157 CheckClosedStreams(); | 189 CheckClosedStreams(); |
| 158 CloseStream(2); | 190 CloseStream(2); |
| 159 CheckClosedStreams(); | 191 CheckClosedStreams(); |
| 160 } | 192 } |
| 161 | 193 |
| 162 TEST_F(QuicSessionTest, IsClosedStreamPeerCreated) { | 194 TEST_F(QuicSessionTest, IsClosedStreamPeerCreated) { |
| 163 session_.GetIncomingReliableStream(3); | 195 ReliableQuicStream* stream3 = session_.GetIncomingReliableStream(3); |
| 164 session_.GetIncomingReliableStream(5); | 196 ReliableQuicStreamPeer::SetHeadersDecompressed(stream3, true); |
| 197 ReliableQuicStream* stream5 = session_.GetIncomingReliableStream(5); |
| 198 ReliableQuicStreamPeer::SetHeadersDecompressed(stream5, true); |
| 165 | 199 |
| 166 CheckClosedStreams(); | 200 CheckClosedStreams(); |
| 167 CloseStream(3); | 201 CloseStream(3); |
| 168 CheckClosedStreams(); | 202 CheckClosedStreams(); |
| 169 CloseStream(5); | 203 CloseStream(5); |
| 170 // Create stream id 9, and implicitly 7 | 204 // Create stream id 9, and implicitly 7 |
| 171 session_.GetIncomingReliableStream(9); | 205 ReliableQuicStream* stream9 = session_.GetIncomingReliableStream(9); |
| 206 ReliableQuicStreamPeer::SetHeadersDecompressed(stream9, true); |
| 172 CheckClosedStreams(); | 207 CheckClosedStreams(); |
| 173 // Close 9, but make sure 7 is still not closed | 208 // Close 9, but make sure 7 is still not closed |
| 174 CloseStream(9); | 209 CloseStream(9); |
| 175 CheckClosedStreams(); | 210 CheckClosedStreams(); |
| 176 } | 211 } |
| 177 | 212 |
| 178 TEST_F(QuicSessionTest, StreamIdTooLarge) { | 213 TEST_F(QuicSessionTest, StreamIdTooLarge) { |
| 179 session_.GetIncomingReliableStream(3); | 214 session_.GetIncomingReliableStream(3); |
| 180 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID)); | 215 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID)); |
| 181 session_.GetIncomingReliableStream(105); | 216 session_.GetIncomingReliableStream(105); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 | 257 |
| 223 InSequence s; | 258 InSequence s; |
| 224 EXPECT_CALL(*stream2, OnCanWrite()); | 259 EXPECT_CALL(*stream2, OnCanWrite()); |
| 225 EXPECT_CALL(*stream4, OnCanWrite()); | 260 EXPECT_CALL(*stream4, OnCanWrite()); |
| 226 EXPECT_TRUE(session_.OnCanWrite()); | 261 EXPECT_TRUE(session_.OnCanWrite()); |
| 227 } | 262 } |
| 228 | 263 |
| 229 // Regression test for http://crbug.com/248737 | 264 // Regression test for http://crbug.com/248737 |
| 230 TEST_F(QuicSessionTest, OutOfOrderHeaders) { | 265 TEST_F(QuicSessionTest, OutOfOrderHeaders) { |
| 231 QuicSpdyCompressor compressor; | 266 QuicSpdyCompressor compressor; |
| 232 SpdyHeaderBlock headers; | |
| 233 headers[":host"] = "www.google.com"; | |
| 234 headers[":path"] = "/index.hml"; | |
| 235 headers[":scheme"] = "http"; | |
| 236 vector<QuicStreamFrame> frames; | 267 vector<QuicStreamFrame> frames; |
| 237 QuicPacketHeader header; | 268 QuicPacketHeader header; |
| 238 header.public_header.guid = session_.guid(); | 269 header.public_header.guid = session_.guid(); |
| 239 | 270 |
| 240 TestStream* stream2 = session_.CreateOutgoingReliableStream(); | 271 TestStream* stream2 = session_.CreateOutgoingReliableStream(); |
| 241 TestStream* stream4 = session_.CreateOutgoingReliableStream(); | 272 TestStream* stream4 = session_.CreateOutgoingReliableStream(); |
| 242 stream2->CloseWriteSide(); | 273 stream2->CloseWriteSide(); |
| 243 stream4->CloseWriteSide(); | 274 stream4->CloseWriteSide(); |
| 244 | 275 |
| 245 // Create frame with headers for stream2. | 276 // Create frame with headers for stream2. |
| 246 string compressed_headers1 = compressor.CompressHeaders(headers); | 277 string compressed_headers1 = compressor.CompressHeaders(headers_); |
| 247 QuicStreamFrame frame1(stream2->id(), false, 0, compressed_headers1); | 278 QuicStreamFrame frame1(stream2->id(), false, 0, compressed_headers1); |
| 248 | 279 |
| 249 // Create frame with headers for stream4. | 280 // Create frame with headers for stream4. |
| 250 string compressed_headers2 = compressor.CompressHeaders(headers); | 281 string compressed_headers2 = compressor.CompressHeaders(headers_); |
| 251 QuicStreamFrame frame2(stream4->id(), true, 0, compressed_headers2); | 282 QuicStreamFrame frame2(stream4->id(), true, 0, compressed_headers2); |
| 252 | 283 |
| 253 // Process the second frame first. This will cause the headers to | 284 // Process the second frame first. This will cause the headers to |
| 254 // be queued up and processed after the first frame is processed. | 285 // be queued up and processed after the first frame is processed. |
| 255 frames.push_back(frame2); | 286 frames.push_back(frame2); |
| 256 session_.OnPacket(IPEndPoint(), IPEndPoint(), header, frames); | 287 session_.OnPacket(IPEndPoint(), IPEndPoint(), header, frames); |
| 257 | 288 |
| 258 // Process the first frame, and un-cork the buffered headers. | 289 // Process the first frame, and un-cork the buffered headers. |
| 259 frames[0] = frame1; | 290 frames[0] = frame1; |
| 260 session_.OnPacket(IPEndPoint(), IPEndPoint(), header, frames); | 291 session_.OnPacket(IPEndPoint(), IPEndPoint(), header, frames); |
| 261 | 292 |
| 262 // Ensure that the streams actually close and we don't DCHECK. | 293 // Ensure that the streams actually close and we don't DCHECK. |
| 263 session_.ConnectionClose(QUIC_CONNECTION_TIMED_OUT, true); | 294 connection_->CloseConnection(QUIC_CONNECTION_TIMED_OUT, true); |
| 264 } | 295 } |
| 265 | 296 |
| 266 TEST_F(QuicSessionTest, SendGoAway) { | 297 TEST_F(QuicSessionTest, SendGoAway) { |
| 267 // After sending a GoAway, ensure new incoming streams cannot be created and | 298 // After sending a GoAway, ensure new incoming streams cannot be created and |
| 268 // result in a RST being sent. | 299 // result in a RST being sent. |
| 269 EXPECT_CALL(*connection_, | 300 EXPECT_CALL(*connection_, |
| 270 SendGoAway(QUIC_PEER_GOING_AWAY, 0u, "Going Away.")); | 301 SendGoAway(QUIC_PEER_GOING_AWAY, 0u, "Going Away.")); |
| 271 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); | 302 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); |
| 272 EXPECT_TRUE(session_.goaway_sent()); | 303 EXPECT_TRUE(session_.goaway_sent()); |
| 273 | 304 |
| 274 EXPECT_CALL(*connection_, SendRstStream(3u, QUIC_STREAM_PEER_GOING_AWAY)); | 305 EXPECT_CALL(*connection_, SendRstStream(3u, QUIC_STREAM_PEER_GOING_AWAY)); |
| 275 EXPECT_FALSE(session_.GetIncomingReliableStream(3u)); | 306 EXPECT_FALSE(session_.GetIncomingReliableStream(3u)); |
| 276 } | 307 } |
| 277 | 308 |
| 278 TEST_F(QuicSessionTest, IncreasedTimeoutAfterCryptoHandshake) { | 309 TEST_F(QuicSessionTest, IncreasedTimeoutAfterCryptoHandshake) { |
| 279 EXPECT_EQ(kDefaultInitialTimeoutSecs, | 310 EXPECT_EQ(kDefaultInitialTimeoutSecs, |
| 280 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 311 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
| 281 CryptoHandshakeMessage msg; | 312 CryptoHandshakeMessage msg; |
| 282 session_.crypto_stream_.OnHandshakeMessage(msg); | 313 session_.crypto_stream_.OnHandshakeMessage(msg); |
| 283 EXPECT_EQ(kDefaultTimeoutSecs, | 314 EXPECT_EQ(kDefaultTimeoutSecs, |
| 284 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 315 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
| 285 } | 316 } |
| 286 | 317 |
| 318 TEST_F(QuicSessionTest, ZombieStream) { |
| 319 StrictMock<MockConnection>* connection = |
| 320 new StrictMock<MockConnection>(guid_, IPEndPoint(), false); |
| 321 TestSession session(connection, /*is_server=*/ false); |
| 322 |
| 323 TestStream* stream3 = session.CreateOutgoingReliableStream(); |
| 324 EXPECT_EQ(3u, stream3->id()); |
| 325 TestStream* stream5 = session.CreateOutgoingReliableStream(); |
| 326 EXPECT_EQ(5u, stream5->id()); |
| 327 |
| 328 // Reset the stream, but since the headers have not been decompressed |
| 329 // it will become a zombie and will continue to process data |
| 330 // until the headers are decompressed. |
| 331 EXPECT_CALL(*connection, SendRstStream(3, QUIC_STREAM_CANCELLED)); |
| 332 session.SendRstStream(3, QUIC_STREAM_CANCELLED); |
| 333 |
| 334 vector<QuicStreamFrame> frames; |
| 335 QuicPacketHeader header; |
| 336 header.public_header.guid = session_.guid(); |
| 337 |
| 338 // Create frame with headers for stream2. |
| 339 QuicSpdyCompressor compressor; |
| 340 string compressed_headers1 = compressor.CompressHeaders(headers_); |
| 341 QuicStreamFrame frame1(stream3->id(), false, 0, compressed_headers1); |
| 342 |
| 343 // Process the second frame first. This will cause the headers to |
| 344 // be queued up and processed after the first frame is processed. |
| 345 frames.push_back(frame1); |
| 346 EXPECT_FALSE(stream3->headers_decompressed()); |
| 347 session.OnPacket(IPEndPoint(), IPEndPoint(), header, frames); |
| 348 |
| 349 EXPECT_TRUE(connection->connected()); |
| 350 } |
| 351 |
| 287 } // namespace | 352 } // namespace |
| 288 } // namespace test | 353 } // namespace test |
| 289 } // namespace net | 354 } // namespace net |
| OLD | NEW |