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/tools/quic/quic_client_session.h" | 5 #include "net/tools/quic/quic_client_session.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" | 9 #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" |
10 #include "net/quic/core/spdy_utils.h" | 10 #include "net/quic/core/spdy_utils.h" |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 192 } |
193 | 193 |
194 TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) { | 194 TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) { |
195 EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); | 195 EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); |
196 | 196 |
197 const uint32_t kServerMaxIncomingStreams = 1; | 197 const uint32_t kServerMaxIncomingStreams = 1; |
198 CompleteCryptoHandshake(kServerMaxIncomingStreams); | 198 CompleteCryptoHandshake(kServerMaxIncomingStreams); |
199 | 199 |
200 QuicSpdyClientStream* stream = | 200 QuicSpdyClientStream* stream = |
201 session_->CreateOutgoingDynamicStream(kDefaultPriority); | 201 session_->CreateOutgoingDynamicStream(kDefaultPriority); |
202 ASSERT_TRUE(stream); | 202 ASSERT_NE(nullptr, stream); |
203 EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority)); | 203 EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority)); |
204 | 204 |
205 // Close the stream and receive an RST frame to remove the unfinished stream | 205 // Close the stream and receive an RST frame to remove the unfinished stream |
206 session_->CloseStream(stream->id()); | 206 session_->CloseStream(stream->id()); |
207 session_->OnRstStream( | 207 session_->OnRstStream( |
208 QuicRstStreamFrame(stream->id(), QUIC_RST_ACKNOWLEDGEMENT, 0)); | 208 QuicRstStreamFrame(stream->id(), QUIC_RST_ACKNOWLEDGEMENT, 0)); |
209 // Check that a new one can be created. | 209 // Check that a new one can be created. |
210 EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); | 210 EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); |
211 stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); | 211 stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); |
212 EXPECT_TRUE(stream); | 212 EXPECT_NE(nullptr, stream); |
| 213 } |
| 214 |
| 215 TEST_P(QuicClientSessionTest, ResetAndTrailers) { |
| 216 // Tests the situation in which the client sends a RST at the same time that |
| 217 // the server sends trailing headers (trailers). Receipt of the trailers by |
| 218 // the client should result in all outstanding stream state being tidied up |
| 219 // (including flow control, and number of available outgoing streams). |
| 220 const uint32_t kServerMaxIncomingStreams = 1; |
| 221 CompleteCryptoHandshake(kServerMaxIncomingStreams); |
| 222 |
| 223 QuicSpdyClientStream* stream = |
| 224 session_->CreateOutgoingDynamicStream(kDefaultPriority); |
| 225 ASSERT_NE(nullptr, stream); |
| 226 EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority)); |
| 227 |
| 228 QuicStreamId stream_id = stream->id(); |
| 229 EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(1); |
| 230 session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0); |
| 231 |
| 232 // A new stream cannot be created as the reset stream still counts as an open |
| 233 // outgoing stream until closed by the server. |
| 234 EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams()); |
| 235 stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); |
| 236 EXPECT_EQ(nullptr, stream); |
| 237 |
| 238 // The stream receives trailers with final byte offset: this is one of three |
| 239 // ways that a peer can signal the end of a stream (the others being RST, |
| 240 // stream data + FIN). |
| 241 QuicHeaderList trailers; |
| 242 trailers.OnHeaderBlockStart(); |
| 243 trailers.OnHeader(kFinalOffsetHeaderKey, "0"); |
| 244 trailers.OnHeaderBlockEnd(0); |
| 245 session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers); |
| 246 |
| 247 if (FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers) { |
| 248 // The stream is now complete from the client's perspective, and it should |
| 249 // be able to create a new outgoing stream. |
| 250 EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); |
| 251 stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); |
| 252 EXPECT_NE(nullptr, stream); |
| 253 } else { |
| 254 // The old behavior: receiving trailers with final offset does not trigger |
| 255 // cleanup of local stream state. New streams cannot be created. |
| 256 EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams()); |
| 257 stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); |
| 258 EXPECT_EQ(nullptr, stream); |
| 259 } |
| 260 } |
| 261 |
| 262 TEST_P(QuicClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) { |
| 263 // Tests the situation where the client has sent a RST to the server, and has |
| 264 // received trailing headers with a malformed final byte offset value. |
| 265 FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers = true; |
| 266 CompleteCryptoHandshake(); |
| 267 |
| 268 QuicSpdyClientStream* stream = |
| 269 session_->CreateOutgoingDynamicStream(kDefaultPriority); |
| 270 ASSERT_NE(nullptr, stream); |
| 271 |
| 272 // Send the RST, which results in the stream being closed locally (but some |
| 273 // state remains while the client waits for a response from the server). |
| 274 QuicStreamId stream_id = stream->id(); |
| 275 EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(1); |
| 276 session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0); |
| 277 |
| 278 // The stream receives trailers with final byte offset, but the header value |
| 279 // is non-numeric and should be treated as malformed. |
| 280 QuicHeaderList trailers; |
| 281 trailers.OnHeaderBlockStart(); |
| 282 trailers.OnHeader(kFinalOffsetHeaderKey, "invalid non-numeric value"); |
| 283 trailers.OnHeaderBlockEnd(0); |
| 284 |
| 285 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1); |
| 286 session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers); |
213 } | 287 } |
214 | 288 |
215 TEST_P(QuicClientSessionTest, GoAwayReceived) { | 289 TEST_P(QuicClientSessionTest, GoAwayReceived) { |
216 CompleteCryptoHandshake(); | 290 CompleteCryptoHandshake(); |
217 | 291 |
218 // After receiving a GoAway, I should no longer be able to create outgoing | 292 // After receiving a GoAway, I should no longer be able to create outgoing |
219 // streams. | 293 // streams. |
220 session_->connection()->OnGoAwayFrame( | 294 session_->connection()->OnGoAwayFrame( |
221 QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away.")); | 295 QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away.")); |
222 EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority)); | 296 EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority)); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 QuicClientPromisedInfo* promised = | 558 QuicClientPromisedInfo* promised = |
485 session_->GetPromisedById(promised_stream_id_); | 559 session_->GetPromisedById(promised_stream_id_); |
486 EXPECT_NE(promised, nullptr); | 560 EXPECT_NE(promised, nullptr); |
487 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); | 561 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); |
488 EXPECT_EQ(session_->GetPromisedStream(promised_stream_id_), nullptr); | 562 EXPECT_EQ(session_->GetPromisedStream(promised_stream_id_), nullptr); |
489 } | 563 } |
490 | 564 |
491 } // namespace | 565 } // namespace |
492 } // namespace test | 566 } // namespace test |
493 } // namespace net | 567 } // namespace net |
OLD | NEW |