1 // Copyright 2012 The Chromium Authors
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 <cmath>
6 #include <utility>
7 #include <vector>
8
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_piece.h"
17 #include "base/task/single_thread_task_runner.h"
18 #include "base/test/metrics/histogram_tester.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "base/test/test_file_util.h"
21 #include "build/build_config.h"
22 #include "net/base/auth.h"
23 #include "net/base/chunked_upload_data_stream.h"
24 #include "net/base/completion_once_callback.h"
25 #include "net/base/elements_upload_data_stream.h"
26 #include "net/base/features.h"
27 #include "net/base/hex_utils.h"
28 #include "net/base/ip_endpoint.h"
29 #include "net/base/network_anonymization_key.h"
30 #include "net/base/proxy_delegate.h"
31 #include "net/base/proxy_server.h"
32 #include "net/base/proxy_string_util.h"
33 #include "net/base/request_priority.h"
34 #include "net/base/schemeful_site.h"
35 #include "net/base/test_proxy_delegate.h"
36 #include "net/base/upload_bytes_element_reader.h"
37 #include "net/base/upload_file_element_reader.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/dns/public/secure_dns_policy.h"
40 #include "net/http/http_auth_scheme.h"
41 #include "net/http/http_connection_info.h"
42 #include "net/http/http_network_session.h"
43 #include "net/http/http_network_session_peer.h"
44 #include "net/http/http_network_transaction.h"
45 #include "net/http/http_proxy_connect_job.h"
46 #include "net/http/http_response_info.h"
47 #include "net/http/http_server_properties.h"
48 #include "net/http/http_transaction_test_util.h"
49 #include "net/http/test_upload_data_stream_not_allow_http1.h"
50 #include "net/http/transport_security_state.h"
51 #include "net/log/net_log_event_type.h"
52 #include "net/log/net_log_with_source.h"
53 #include "net/log/test_net_log.h"
54 #include "net/log/test_net_log_util.h"
55 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
56 #include "net/socket/next_proto.h"
57 #include "net/socket/socket_tag.h"
58 #include "net/spdy/alps_decoder.h"
59 #include "net/spdy/buffered_spdy_framer.h"
60 #include "net/spdy/spdy_http_stream.h"
61 #include "net/spdy/spdy_http_utils.h"
62 #include "net/spdy/spdy_session.h"
63 #include "net/spdy/spdy_session_pool.h"
64 #include "net/spdy/spdy_test_util_common.h"
65 #include "net/ssl/ssl_connection_status_flags.h"
66 #include "net/test/cert_test_util.h"
67 #include "net/test/gtest_util.h"
68 #include "net/test/test_data_directory.h"
69 #include "net/test/test_with_task_environment.h"
70 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
71 #include "net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h"
72 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
73 #include "net/url_request/url_request_context.h"
74 #include "net/url_request/url_request_context_builder.h"
75 #include "net/url_request/url_request_test_util.h"
76 #include "net/websockets/websocket_test_util.h"
77 #include "testing/gmock/include/gmock/gmock.h"
78 #include "testing/platform_test.h"
79 #include "url/gurl.h"
80 #include "url/url_constants.h"
81
82 using net::test::IsError;
83 using net::test::IsOk;
84
85 //-----------------------------------------------------------------------------
86
87 namespace net {
88
89 namespace {
90
91 using testing::Each;
92 using testing::Eq;
93
94 const int32_t kBufferSize = SpdyHttpStream::kRequestBodyBufferSize;
95
96 } // namespace
97
98 const char kPushedUrl[] = "https://www.example.org/foo.dat";
99
100 class SpdyNetworkTransactionTest : public TestWithTaskEnvironment,
101 public ::testing::WithParamInterface<bool> {
102 protected:
SpdyNetworkTransactionTest()103 SpdyNetworkTransactionTest()
104 : TestWithTaskEnvironment(
105 base::test::TaskEnvironment::TimeSource::MOCK_TIME),
106 default_url_(kDefaultUrl),
107 host_port_pair_(HostPortPair::FromURL(default_url_)),
108 spdy_util_(/*use_priority_header=*/true) {
109 if (PriorityHeaderEnabled()) {
110 feature_list_.InitAndEnableFeature(net::features::kPriorityHeader);
111 } else {
112 feature_list_.InitAndDisableFeature(net::features::kPriorityHeader);
113 }
114 }
115
~SpdyNetworkTransactionTest()116 ~SpdyNetworkTransactionTest() override {
117 // UploadDataStream may post a deletion task back to the message loop on
118 // destruction.
119 upload_data_stream_.reset();
120 base::RunLoop().RunUntilIdle();
121 }
122
SetUp()123 void SetUp() override {
124 request_.method = "GET";
125 request_.url = GURL(kDefaultUrl);
126 request_.traffic_annotation =
127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
128 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
129 }
130
131 struct TransactionHelperResult {
132 int rv;
133 std::string status_line;
134 std::string response_data;
135 HttpResponseInfo response_info;
136 };
137
138 // A helper class that handles all the initial npn/ssl setup.
139 class NormalSpdyTransactionHelper {
140 public:
NormalSpdyTransactionHelper(const HttpRequestInfo & request,RequestPriority priority,const NetLogWithSource & log,std::unique_ptr<SpdySessionDependencies> session_deps)141 NormalSpdyTransactionHelper(
142 const HttpRequestInfo& request,
143 RequestPriority priority,
144 const NetLogWithSource& log,
145 std::unique_ptr<SpdySessionDependencies> session_deps)
146 : request_(request),
147 priority_(priority),
148 session_deps_(session_deps.get() == nullptr
149 ? std::make_unique<SpdySessionDependencies>()
150 : std::move(session_deps)),
151 log_(log) {
152 session_deps_->net_log = log.net_log();
153 session_ =
154 SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
155 }
156
~NormalSpdyTransactionHelper()157 ~NormalSpdyTransactionHelper() {
158 // Any test which doesn't close the socket by sending it an EOF will
159 // have a valid session left open, which leaks the entire session pool.
160 // This is just fine - in fact, some of our tests intentionally do this
161 // so that we can check consistency of the SpdySessionPool as the test
162 // finishes. If we had put an EOF on the socket, the SpdySession would
163 // have closed and we wouldn't be able to check the consistency.
164
165 // Forcefully close existing sessions here.
166 session()->spdy_session_pool()->CloseAllSessions();
167 }
168
RunPreTestSetup()169 void RunPreTestSetup() {
170 // We're now ready to use SSL-npn SPDY.
171 trans_ =
172 std::make_unique<HttpNetworkTransaction>(priority_, session_.get());
173 }
174
175 // Start the transaction, read some data, finish.
RunDefaultTest()176 void RunDefaultTest() {
177 if (!StartDefaultTest())
178 return;
179 FinishDefaultTest();
180 }
181
StartDefaultTest()182 bool StartDefaultTest() {
183 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
184
185 // We expect an IO Pending or some sort of error.
186 EXPECT_LT(output_.rv, 0);
187 return output_.rv == ERR_IO_PENDING;
188 }
189
FinishDefaultTest()190 void FinishDefaultTest() {
191 output_.rv = callback_.WaitForResult();
192 // Finish async network reads/writes.
193 base::RunLoop().RunUntilIdle();
194 if (output_.rv != OK) {
195 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
196 return;
197 }
198
199 // Verify responses.
200 const HttpResponseInfo* response = trans_->GetResponseInfo();
201 ASSERT_TRUE(response);
202 ASSERT_TRUE(response->headers);
203 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response->connection_info);
204 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
205 EXPECT_TRUE(response->was_fetched_via_spdy);
206 EXPECT_TRUE(response->was_alpn_negotiated);
207 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
208 EXPECT_EQ(443, response->remote_endpoint.port());
209 output_.status_line = response->headers->GetStatusLine();
210 output_.response_info = *response; // Make a copy so we can verify.
211 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
212 }
213
FinishDefaultTestWithoutVerification()214 void FinishDefaultTestWithoutVerification() {
215 output_.rv = callback_.WaitForResult();
216 // Finish async network reads/writes.
217 base::RunLoop().RunUntilIdle();
218 if (output_.rv != OK)
219 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
220 }
221
WaitForCallbackToComplete()222 void WaitForCallbackToComplete() { output_.rv = callback_.WaitForResult(); }
223
224 // Most tests will want to call this function. In particular, the MockReads
225 // should end with an empty read, and that read needs to be processed to
226 // ensure proper deletion of the spdy_session_pool.
VerifyDataConsumed()227 void VerifyDataConsumed() {
228 for (const SocketDataProvider* provider : data_vector_) {
229 EXPECT_TRUE(provider->AllReadDataConsumed());
230 EXPECT_TRUE(provider->AllWriteDataConsumed());
231 }
232 }
233
234 // Occasionally a test will expect to error out before certain reads are
235 // processed. In that case we want to explicitly ensure that the reads were
236 // not processed.
VerifyDataNotConsumed()237 void VerifyDataNotConsumed() {
238 for (const SocketDataProvider* provider : data_vector_) {
239 EXPECT_FALSE(provider->AllReadDataConsumed());
240 EXPECT_FALSE(provider->AllWriteDataConsumed());
241 }
242 }
243
RunToCompletion(SocketDataProvider * data)244 void RunToCompletion(SocketDataProvider* data) {
245 RunPreTestSetup();
246 AddData(data);
247 RunDefaultTest();
248 VerifyDataConsumed();
249 }
250
RunToCompletionWithSSLData(SocketDataProvider * data,std::unique_ptr<SSLSocketDataProvider> ssl_provider)251 void RunToCompletionWithSSLData(
252 SocketDataProvider* data,
253 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
254 RunPreTestSetup();
255 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
256 RunDefaultTest();
257 VerifyDataConsumed();
258 }
259
AddData(SocketDataProvider * data)260 void AddData(SocketDataProvider* data) {
261 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
262 ssl_provider->ssl_info.cert =
263 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
264 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
265 }
266
AddDataWithSSLSocketDataProvider(SocketDataProvider * data,std::unique_ptr<SSLSocketDataProvider> ssl_provider)267 void AddDataWithSSLSocketDataProvider(
268 SocketDataProvider* data,
269 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
270 data_vector_.push_back(data);
271 if (ssl_provider->next_proto == kProtoUnknown)
272 ssl_provider->next_proto = kProtoHTTP2;
273
274 session_deps_->socket_factory->AddSSLSocketDataProvider(
275 ssl_provider.get());
276 ssl_vector_.push_back(std::move(ssl_provider));
277
278 session_deps_->socket_factory->AddSocketDataProvider(data);
279 }
280
GetSpdySessionCount()281 size_t GetSpdySessionCount() {
282 std::unique_ptr<base::Value> value(
283 session_->spdy_session_pool()->SpdySessionPoolInfoToValue());
284 CHECK(value && value->is_list());
285 return value->GetList().size();
286 }
287
trans()288 HttpNetworkTransaction* trans() { return trans_.get(); }
ResetTrans()289 void ResetTrans() { trans_.reset(); }
output()290 const TransactionHelperResult& output() { return output_; }
session() const291 HttpNetworkSession* session() const { return session_.get(); }
session_deps()292 SpdySessionDependencies* session_deps() { return session_deps_.get(); }
293
294 private:
295 typedef std::vector<SocketDataProvider*> DataVector;
296 typedef std::vector<std::unique_ptr<SSLSocketDataProvider>> SSLVector;
297 typedef std::vector<std::unique_ptr<SocketDataProvider>> AlternateVector;
298 const HttpRequestInfo request_;
299 const RequestPriority priority_;
300 std::unique_ptr<SpdySessionDependencies> session_deps_;
301 std::unique_ptr<HttpNetworkSession> session_;
302 TransactionHelperResult output_;
303 SSLVector ssl_vector_;
304 TestCompletionCallback callback_;
305 std::unique_ptr<HttpNetworkTransaction> trans_;
306 DataVector data_vector_;
307 const NetLogWithSource log_;
308 };
309
310 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
311 int expected_status);
312
313 void ConnectStatusHelper(const MockRead& status);
314
CreateGetPushRequest() const315 [[nodiscard]] HttpRequestInfo CreateGetPushRequest() const {
316 HttpRequestInfo request;
317 request.method = "GET";
318 request.url = GURL(kPushedUrl);
319 request.traffic_annotation =
320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
321 return request;
322 }
323
UsePostRequest()324 void UsePostRequest() {
325 ASSERT_FALSE(upload_data_stream_);
326 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
327 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
328 kUploadData, kUploadDataSize));
329 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
330 std::move(element_readers), 0);
331
332 request_.method = "POST";
333 request_.upload_data_stream = upload_data_stream_.get();
334 }
335
UseFilePostRequest()336 void UseFilePostRequest() {
337 ASSERT_FALSE(upload_data_stream_);
338 base::FilePath file_path;
339 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
340 CHECK(base::WriteFile(file_path, kUploadData));
341
342 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
343 element_readers.push_back(std::make_unique<UploadFileElementReader>(
344 base::SingleThreadTaskRunner::GetCurrentDefault().get(), file_path, 0,
345 kUploadDataSize, base::Time()));
346 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
347 std::move(element_readers), 0);
348
349 request_.method = "POST";
350 request_.upload_data_stream = upload_data_stream_.get();
351 request_.traffic_annotation =
352 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
353 }
354
UseUnreadableFilePostRequest()355 void UseUnreadableFilePostRequest() {
356 ASSERT_FALSE(upload_data_stream_);
357 base::FilePath file_path;
358 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
359 CHECK(base::WriteFile(file_path, kUploadData));
360 CHECK(base::MakeFileUnreadable(file_path));
361
362 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
363 element_readers.push_back(std::make_unique<UploadFileElementReader>(
364 base::SingleThreadTaskRunner::GetCurrentDefault().get(), file_path, 0,
365 kUploadDataSize, base::Time()));
366 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
367 std::move(element_readers), 0);
368
369 request_.method = "POST";
370 request_.upload_data_stream = upload_data_stream_.get();
371 }
372
UseComplexPostRequest()373 void UseComplexPostRequest() {
374 ASSERT_FALSE(upload_data_stream_);
375 const int kFileRangeOffset = 1;
376 const int kFileRangeLength = 3;
377 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
378
379 base::FilePath file_path;
380 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
381 CHECK(base::WriteFile(file_path, kUploadData));
382
383 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
384 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
385 kUploadData, kFileRangeOffset));
386 element_readers.push_back(std::make_unique<UploadFileElementReader>(
387 base::SingleThreadTaskRunner::GetCurrentDefault().get(), file_path,
388 kFileRangeOffset, kFileRangeLength, base::Time()));
389 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
390 kUploadData + kFileRangeOffset + kFileRangeLength,
391 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
392 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
393 std::move(element_readers), 0);
394
395 request_.method = "POST";
396 request_.upload_data_stream = upload_data_stream_.get();
397 }
398
UseChunkedPostRequest()399 void UseChunkedPostRequest() {
400 ASSERT_FALSE(upload_chunked_data_stream_);
401 upload_chunked_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
402 request_.method = "POST";
403 request_.upload_data_stream = upload_chunked_data_stream_.get();
404 }
405
406 // Read the result of a particular transaction, knowing that we've got
407 // multiple transactions in the read pipeline; so as we read, we may have
408 // to skip over data destined for other transactions while we consume
409 // the data for |trans|.
ReadResult(HttpNetworkTransaction * trans,std::string * result)410 int ReadResult(HttpNetworkTransaction* trans, std::string* result) {
411 const int kSize = 3000;
412
413 int bytes_read = 0;
414 scoped_refptr<IOBufferWithSize> buf =
415 base::MakeRefCounted<IOBufferWithSize>(kSize);
416 TestCompletionCallback callback;
417 while (true) {
418 int rv = trans->Read(buf.get(), kSize, callback.callback());
419 if (rv == ERR_IO_PENDING) {
420 rv = callback.WaitForResult();
421 } else if (rv <= 0) {
422 break;
423 }
424 result->append(buf->data(), rv);
425 bytes_read += rv;
426 }
427 return bytes_read;
428 }
429
VerifyStreamsClosed(const NormalSpdyTransactionHelper & helper)430 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
431 // This lengthy block is reaching into the pool to dig out the active
432 // session. Once we have the session, we verify that the streams are
433 // all closed and not leaked at this point.
434 SpdySessionKey key(HostPortPair::FromURL(request_.url),
435 ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
436 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
437 request_.network_anonymization_key,
438 SecureDnsPolicy::kAllow);
439 HttpNetworkSession* session = helper.session();
440 base::WeakPtr<SpdySession> spdy_session =
441 session->spdy_session_pool()->FindAvailableSession(
442 key, /* enable_ip_based_pooling = */ true,
443 /* is_websocket = */ false, log_);
444 ASSERT_TRUE(spdy_session);
445 EXPECT_EQ(0u, num_active_streams(spdy_session));
446 }
447
DeleteSessionCallback(NormalSpdyTransactionHelper * helper,int result)448 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
449 int result) {
450 helper->ResetTrans();
451 }
452
StartTransactionCallback(HttpNetworkSession * session,GURL url,NetLogWithSource log,int result)453 static void StartTransactionCallback(HttpNetworkSession* session,
454 GURL url,
455 NetLogWithSource log,
456 int result) {
457 HttpRequestInfo request;
458 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
459 TestCompletionCallback callback;
460 request.method = "GET";
461 request.url = url;
462 request.traffic_annotation =
463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
464 int rv = trans.Start(&request, callback.callback(), log);
465 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
466 callback.WaitForResult();
467 }
468
upload_chunked_data_stream()469 ChunkedUploadDataStream* upload_chunked_data_stream() {
470 return upload_chunked_data_stream_.get();
471 }
472
num_active_streams(base::WeakPtr<SpdySession> session)473 size_t num_active_streams(base::WeakPtr<SpdySession> session) {
474 return session->active_streams_.size();
475 }
476
spdy_stream_hi_water_mark(base::WeakPtr<SpdySession> session)477 static spdy::SpdyStreamId spdy_stream_hi_water_mark(
478 base::WeakPtr<SpdySession> session) {
479 return session->stream_hi_water_mark_;
480 }
481
FastForwardByCallback(base::TimeDelta delta)482 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
483 return base::BindRepeating(&SpdyNetworkTransactionTest::FastForwardBy,
484 base::Unretained(this), delta);
485 }
486
PriorityHeaderEnabled() const487 bool PriorityHeaderEnabled() const { return GetParam(); }
488
489 const GURL default_url_;
490 const HostPortPair host_port_pair_;
491 HttpRequestInfo request_;
492 SpdyTestUtil spdy_util_;
493 const NetLogWithSource log_;
494
495 private:
496 std::unique_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
497 std::unique_ptr<UploadDataStream> upload_data_stream_;
498 base::ScopedTempDir temp_dir_;
499 base::test::ScopedFeatureList feature_list_;
500 };
501
502 INSTANTIATE_TEST_SUITE_P(All,
503 SpdyNetworkTransactionTest,
504 testing::Values(true, false));
505
506 // Verify HttpNetworkTransaction constructor.
TEST_P(SpdyNetworkTransactionTest,Constructor)507 TEST_P(SpdyNetworkTransactionTest, Constructor) {
508 auto session_deps = std::make_unique<SpdySessionDependencies>();
509 std::unique_ptr<HttpNetworkSession> session(
510 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
511 auto trans =
512 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
513 }
514
TEST_P(SpdyNetworkTransactionTest,Get)515 TEST_P(SpdyNetworkTransactionTest, Get) {
516 // Construct the request.
517 spdy::SpdySerializedFrame req(
518 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
519 MockWrite writes[] = {CreateMockWrite(req, 0)};
520
521 spdy::SpdySerializedFrame resp(
522 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
523 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
524 MockRead reads[] = {
525 CreateMockRead(resp, 1), CreateMockRead(body, 2),
526 MockRead(ASYNC, 0, 3) // EOF
527 };
528
529 SequencedSocketData data(reads, writes);
530 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
531 helper.RunToCompletion(&data);
532 TransactionHelperResult out = helper.output();
533 EXPECT_THAT(out.rv, IsOk());
534 EXPECT_EQ("HTTP/1.1 200", out.status_line);
535 EXPECT_EQ("hello!", out.response_data);
536 }
537
TEST_P(SpdyNetworkTransactionTest,SetPriority)538 TEST_P(SpdyNetworkTransactionTest, SetPriority) {
539 for (bool set_priority_before_starting_transaction : {true, false}) {
540 SpdyTestUtil spdy_test_util(/*use_priority_header=*/true);
541 spdy::SpdySerializedFrame req(
542 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
543 MockWrite writes[] = {CreateMockWrite(req, 0)};
544
545 spdy::SpdySerializedFrame resp(
546 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
547 spdy::SpdySerializedFrame body(
548 spdy_test_util.ConstructSpdyDataFrame(1, true));
549 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
550 MockRead(ASYNC, 0, 3)};
551
552 SequencedSocketData data(reads, writes);
553 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_, nullptr);
554 helper.RunPreTestSetup();
555 helper.AddData(&data);
556
557 if (set_priority_before_starting_transaction) {
558 helper.trans()->SetPriority(LOWEST);
559 EXPECT_TRUE(helper.StartDefaultTest());
560 } else {
561 EXPECT_TRUE(helper.StartDefaultTest());
562 helper.trans()->SetPriority(LOWEST);
563 }
564
565 helper.FinishDefaultTest();
566 helper.VerifyDataConsumed();
567
568 TransactionHelperResult out = helper.output();
569 EXPECT_THAT(out.rv, IsOk());
570 EXPECT_EQ("HTTP/1.1 200", out.status_line);
571 EXPECT_EQ("hello!", out.response_data);
572 }
573 }
574
575 // Test that changing the request priority of an existing stream triggers
576 // sending PRIORITY frames in case there are multiple open streams and their
577 // relative priorities change.
TEST_P(SpdyNetworkTransactionTest,SetPriorityOnExistingStream)578 TEST_P(SpdyNetworkTransactionTest, SetPriorityOnExistingStream) {
579 const char* kUrl2 = "https://www.example.org/bar";
580
581 spdy::SpdySerializedFrame req1(
582 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
583 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(kUrl2, 3, MEDIUM));
584 spdy::SpdySerializedFrame priority1(
585 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
586 spdy::SpdySerializedFrame priority2(
587 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
588 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 2),
589 CreateMockWrite(priority1, 4),
590 CreateMockWrite(priority2, 5)};
591
592 spdy::SpdySerializedFrame resp1(
593 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
594 spdy::SpdySerializedFrame resp2(
595 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
596 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
597 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
598 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(resp2, 3),
599 CreateMockRead(body1, 6), CreateMockRead(body2, 7),
600 MockRead(ASYNC, 0, 8)};
601
602 SequencedSocketData data(reads, writes);
603 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_, nullptr);
604 helper.RunPreTestSetup();
605 helper.AddData(&data);
606 EXPECT_TRUE(helper.StartDefaultTest());
607
608 // Open HTTP/2 connection and create first stream.
609 base::RunLoop().RunUntilIdle();
610
611 HttpNetworkTransaction trans2(MEDIUM, helper.session());
612 HttpRequestInfo request2;
613 request2.url = GURL(kUrl2);
614 request2.method = "GET";
615 request2.traffic_annotation =
616 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
617 TestCompletionCallback callback2;
618 int rv = trans2.Start(&request2, callback2.callback(), log_);
619 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
620
621 // Create second stream.
622 base::RunLoop().RunUntilIdle();
623
624 // First request has HIGHEST priority, second request has MEDIUM priority.
625 // Changing the priority of the first request to LOWEST changes their order,
626 // and therefore triggers sending PRIORITY frames.
627 helper.trans()->SetPriority(LOWEST);
628
629 helper.FinishDefaultTest();
630 helper.VerifyDataConsumed();
631
632 TransactionHelperResult out = helper.output();
633 EXPECT_THAT(out.rv, IsOk());
634 EXPECT_EQ("HTTP/1.1 200", out.status_line);
635 EXPECT_EQ("hello!", out.response_data);
636
637 rv = callback2.WaitForResult();
638 ASSERT_THAT(rv, IsOk());
639 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
640 ASSERT_TRUE(response2);
641 ASSERT_TRUE(response2->headers);
642 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
643 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
644 }
645
646 // Create two requests: a lower priority one first, then a higher priority one.
647 // Test that the second request gets sent out first.
TEST_P(SpdyNetworkTransactionTest,RequestsOrderedByPriority)648 TEST_P(SpdyNetworkTransactionTest, RequestsOrderedByPriority) {
649 const char* kUrl2 = "https://www.example.org/foo";
650
651 // First send second request on stream 1, then first request on stream 3.
652 spdy::SpdySerializedFrame req2(
653 spdy_util_.ConstructSpdyGet(kUrl2, 1, HIGHEST));
654 spdy::SpdySerializedFrame req1(
655 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOW));
656 MockWrite writes[] = {CreateMockWrite(req2, 0), CreateMockWrite(req1, 1)};
657
658 spdy::SpdySerializedFrame resp2(
659 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
660 spdy::SpdySerializedFrame resp1(
661 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
662 spdy::SpdySerializedFrame body2(
663 spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true));
664 spdy::SpdySerializedFrame body1(
665 spdy_util_.ConstructSpdyDataFrame(3, "stream 3", true));
666 MockRead reads[] = {CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
667 CreateMockRead(resp1, 4), CreateMockRead(body1, 5),
668 MockRead(ASYNC, 0, 6)};
669
670 SequencedSocketData data(reads, writes);
671 NormalSpdyTransactionHelper helper(request_, LOW, log_, nullptr);
672 helper.RunPreTestSetup();
673 helper.AddData(&data);
674
675 // Create HTTP/2 connection. This is necessary because starting the first
676 // transaction does not create the connection yet, so the second request
677 // could not use the same connection, whereas running the message loop after
678 // starting the first transaction would call Socket::Write() with the first
679 // HEADERS frame, so the second transaction could not get ahead of it.
680 SpdySessionKey key(HostPortPair("www.example.org", 443), ProxyChain::Direct(),
681 PRIVACY_MODE_DISABLED,
682 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
683 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
684 auto spdy_session = CreateSpdySession(helper.session(), key, log_);
685 EXPECT_TRUE(spdy_session);
686
687 // Start first transaction.
688 EXPECT_TRUE(helper.StartDefaultTest());
689
690 // Start second transaction.
691 HttpNetworkTransaction trans2(HIGHEST, helper.session());
692 HttpRequestInfo request2;
693 request2.url = GURL(kUrl2);
694 request2.method = "GET";
695 request2.traffic_annotation =
696 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
697 TestCompletionCallback callback2;
698 int rv = trans2.Start(&request2, callback2.callback(), log_);
699 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
700
701 // Complete first transaction and verify results.
702 helper.FinishDefaultTest();
703 helper.VerifyDataConsumed();
704
705 TransactionHelperResult out = helper.output();
706 EXPECT_THAT(out.rv, IsOk());
707 EXPECT_EQ("HTTP/1.1 200", out.status_line);
708 EXPECT_EQ("stream 3", out.response_data);
709
710 // Complete second transaction and verify results.
711 rv = callback2.WaitForResult();
712 ASSERT_THAT(rv, IsOk());
713 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
714 ASSERT_TRUE(response2);
715 ASSERT_TRUE(response2->headers);
716 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
717 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
718 std::string response_data;
719 ReadTransaction(&trans2, &response_data);
720 EXPECT_EQ("stream 1", response_data);
721 }
722
723 // Test that already enqueued HEADERS frames are reordered if their relative
724 // priority changes.
TEST_P(SpdyNetworkTransactionTest,QueuedFramesReorderedOnPriorityChange)725 TEST_P(SpdyNetworkTransactionTest, QueuedFramesReorderedOnPriorityChange) {
726 const char* kUrl2 = "https://www.example.org/foo";
727 const char* kUrl3 = "https://www.example.org/bar";
728
729 spdy::SpdySerializedFrame req1(
730 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
731 spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet(kUrl3, 3, MEDIUM));
732 // The headers for request 2 are set before the request is sent to SPDY and
733 // are populated with the initial value (HIGHEST). The priority when it is
734 // actually sent (later) is "LOWEST" which is sent on the actual priority
735 // frame.
736 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(
737 kUrl2, 5, LOWEST, kDefaultPriorityIncremental, HIGHEST));
738 MockWrite writes[] = {MockWrite(ASYNC, ERR_IO_PENDING, 0),
739 CreateMockWrite(req1, 1), CreateMockWrite(req3, 2),
740 CreateMockWrite(req2, 3)};
741
742 spdy::SpdySerializedFrame resp1(
743 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
744 spdy::SpdySerializedFrame resp3(
745 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
746 spdy::SpdySerializedFrame resp2(
747 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
748 spdy::SpdySerializedFrame body1(
749 spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true));
750 spdy::SpdySerializedFrame body3(
751 spdy_util_.ConstructSpdyDataFrame(3, "stream 3", true));
752 spdy::SpdySerializedFrame body2(
753 spdy_util_.ConstructSpdyDataFrame(5, "stream 5", true));
754 MockRead reads[] = {CreateMockRead(resp1, 4), CreateMockRead(body1, 5),
755 CreateMockRead(resp3, 6), CreateMockRead(body3, 7),
756 CreateMockRead(resp2, 8), CreateMockRead(body2, 9),
757 MockRead(ASYNC, 0, 10)};
758
759 SequencedSocketData data(reads, writes);
760 // Priority of first request does not matter, because Socket::Write() will be
761 // called with its HEADERS frame before the other requests start.
762 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
763 helper.RunPreTestSetup();
764 helper.AddData(&data);
765 EXPECT_TRUE(helper.StartDefaultTest());
766
767 // Open HTTP/2 connection, create HEADERS frame for first request, and call
768 // Socket::Write() with that frame. After this, no other request can get
769 // ahead of the first one.
770 base::RunLoop().RunUntilIdle();
771
772 HttpNetworkTransaction trans2(HIGHEST, helper.session());
773 HttpRequestInfo request2;
774 request2.url = GURL(kUrl2);
775 request2.method = "GET";
776 request2.traffic_annotation =
777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
778 TestCompletionCallback callback2;
779 int rv = trans2.Start(&request2, callback2.callback(), log_);
780 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
781
782 HttpNetworkTransaction trans3(MEDIUM, helper.session());
783 HttpRequestInfo request3;
784 request3.url = GURL(kUrl3);
785 request3.method = "GET";
786 request3.traffic_annotation =
787 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
788 TestCompletionCallback callback3;
789 rv = trans3.Start(&request3, callback3.callback(), log_);
790 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
791
792 // Create HEADERS frames for second and third request and enqueue them in
793 // SpdyWriteQueue with their original priorities. Writing of the first
794 // HEADERS frame to the socked still has not completed.
795 base::RunLoop().RunUntilIdle();
796
797 // Second request is of HIGHEST, third of MEDIUM priority. Changing second
798 // request to LOWEST changes their relative order. This should result in
799 // already enqueued frames being reordered within SpdyWriteQueue.
800 trans2.SetPriority(LOWEST);
801
802 // Complete async write of the first HEADERS frame.
803 data.Resume();
804
805 helper.FinishDefaultTest();
806 TransactionHelperResult out = helper.output();
807 EXPECT_THAT(out.rv, IsOk());
808 EXPECT_EQ("HTTP/1.1 200", out.status_line);
809 EXPECT_EQ("stream 1", out.response_data);
810
811 rv = callback2.WaitForResult();
812 ASSERT_THAT(rv, IsOk());
813 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
814 ASSERT_TRUE(response2);
815 ASSERT_TRUE(response2->headers);
816 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
817 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
818 std::string response_data;
819 ReadTransaction(&trans2, &response_data);
820 EXPECT_EQ("stream 5", response_data);
821
822 rv = callback3.WaitForResult();
823 ASSERT_THAT(rv, IsOk());
824 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
825 ASSERT_TRUE(response3);
826 ASSERT_TRUE(response3->headers);
827 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response3->connection_info);
828 EXPECT_EQ("HTTP/1.1 200", response3->headers->GetStatusLine());
829 ReadTransaction(&trans3, &response_data);
830 EXPECT_EQ("stream 3", response_data);
831
832 helper.VerifyDataConsumed();
833 }
834
TEST_P(SpdyNetworkTransactionTest,GetAtEachPriority)835 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
836 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
837 p = RequestPriority(p + 1)) {
838 SpdyTestUtil spdy_test_util(/*use_priority_header=*/true);
839
840 // Construct the request.
841 spdy::SpdySerializedFrame req(
842 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p));
843 MockWrite writes[] = {CreateMockWrite(req, 0)};
844
845 spdy::SpdyPriority spdy_prio = 0;
846 EXPECT_TRUE(GetSpdyPriority(req, &spdy_prio));
847 // this repeats the RequestPriority-->spdy::SpdyPriority mapping from
848 // spdy::SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
849 // sure it's being done right.
850 switch (p) {
851 case HIGHEST:
852 EXPECT_EQ(0, spdy_prio);
853 break;
854 case MEDIUM:
855 EXPECT_EQ(1, spdy_prio);
856 break;
857 case LOW:
858 EXPECT_EQ(2, spdy_prio);
859 break;
860 case LOWEST:
861 EXPECT_EQ(3, spdy_prio);
862 break;
863 case IDLE:
864 EXPECT_EQ(4, spdy_prio);
865 break;
866 case THROTTLED:
867 EXPECT_EQ(5, spdy_prio);
868 break;
869 default:
870 FAIL();
871 }
872
873 spdy::SpdySerializedFrame resp(
874 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
875 spdy::SpdySerializedFrame body(
876 spdy_test_util.ConstructSpdyDataFrame(1, true));
877 MockRead reads[] = {
878 CreateMockRead(resp, 1), CreateMockRead(body, 2),
879 MockRead(ASYNC, 0, 3) // EOF
880 };
881
882 SequencedSocketData data(reads, writes);
883
884 NormalSpdyTransactionHelper helper(request_, p, log_, nullptr);
885 helper.RunToCompletion(&data);
886 TransactionHelperResult out = helper.output();
887 EXPECT_THAT(out.rv, IsOk());
888 EXPECT_EQ("HTTP/1.1 200", out.status_line);
889 EXPECT_EQ("hello!", out.response_data);
890 }
891 }
892
893 // Start three gets simultaniously; making sure that multiplexed
894 // streams work properly.
895
896 // This can't use the TransactionHelper method, since it only
897 // handles a single transaction, and finishes them as soon
898 // as it launches them.
899
900 // TODO(gavinp): create a working generalized TransactionHelper that
901 // can allow multiple streams in flight.
902
TEST_P(SpdyNetworkTransactionTest,ThreeGets)903 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
904 spdy::SpdySerializedFrame req(
905 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
906 spdy::SpdySerializedFrame resp(
907 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
908 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
909 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
910
911 spdy::SpdySerializedFrame req2(
912 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
913 spdy::SpdySerializedFrame resp2(
914 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
915 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
916 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
917
918 spdy::SpdySerializedFrame req3(
919 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST));
920 spdy::SpdySerializedFrame resp3(
921 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
922 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
923 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
924
925 MockWrite writes[] = {
926 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
927 CreateMockWrite(req3, 6),
928 };
929 MockRead reads[] = {
930 CreateMockRead(resp, 1), CreateMockRead(body, 2),
931 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
932 CreateMockRead(resp3, 7), CreateMockRead(body3, 8),
933
934 CreateMockRead(fbody, 9), CreateMockRead(fbody2, 10),
935 CreateMockRead(fbody3, 11),
936
937 MockRead(ASYNC, 0, 12), // EOF
938 };
939 SequencedSocketData data(reads, writes);
940 SequencedSocketData data_placeholder1;
941 SequencedSocketData data_placeholder2;
942
943 TransactionHelperResult out;
944 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
945 helper.RunPreTestSetup();
946 helper.AddData(&data);
947 // We require placeholder data because three get requests are sent out at
948 // the same time which results in three sockets being connected. The first
949 // on will negotiate SPDY and will be used for all requests.
950 helper.AddData(&data_placeholder1);
951 helper.AddData(&data_placeholder2);
952 TestCompletionCallback callback1;
953 TestCompletionCallback callback2;
954 TestCompletionCallback callback3;
955
956 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
957 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
958 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
959
960 out.rv = trans1.Start(&request_, callback1.callback(), log_);
961 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
962 out.rv = trans2.Start(&request_, callback2.callback(), log_);
963 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
964 out.rv = trans3.Start(&request_, callback3.callback(), log_);
965 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
966
967 out.rv = callback1.WaitForResult();
968 ASSERT_THAT(out.rv, IsOk());
969 out.rv = callback3.WaitForResult();
970 ASSERT_THAT(out.rv, IsOk());
971
972 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
973 EXPECT_TRUE(response1->headers);
974 EXPECT_TRUE(response1->was_fetched_via_spdy);
975 out.status_line = response1->headers->GetStatusLine();
976 out.response_info = *response1;
977
978 trans2.GetResponseInfo();
979
980 out.rv = ReadTransaction(&trans1, &out.response_data);
981 helper.VerifyDataConsumed();
982 EXPECT_THAT(out.rv, IsOk());
983
984 EXPECT_THAT(out.rv, IsOk());
985 EXPECT_EQ("HTTP/1.1 200", out.status_line);
986 EXPECT_EQ("hello!hello!", out.response_data);
987 }
988
TEST_P(SpdyNetworkTransactionTest,TwoGetsLateBinding)989 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
990 spdy::SpdySerializedFrame req(
991 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
992 spdy::SpdySerializedFrame resp(
993 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
994 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
995 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
996
997 spdy::SpdySerializedFrame req2(
998 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
999 spdy::SpdySerializedFrame resp2(
1000 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1001 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1002 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
1003
1004 MockWrite writes[] = {
1005 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
1006 };
1007 MockRead reads[] = {
1008 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1009 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
1010 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
1011 MockRead(ASYNC, 0, 8), // EOF
1012 };
1013 SequencedSocketData data(reads, writes);
1014
1015 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
1016 SequencedSocketData data_placeholder;
1017 data_placeholder.set_connect_data(never_finishing_connect);
1018
1019 TransactionHelperResult out;
1020 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1021 helper.RunPreTestSetup();
1022 helper.AddData(&data);
1023 // We require placeholder data because two requests are sent out at
1024 // the same time which results in two sockets being connected. The first
1025 // on will negotiate SPDY and will be used for all requests.
1026 helper.AddData(&data_placeholder);
1027 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1028 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1029
1030 TestCompletionCallback callback1;
1031 TestCompletionCallback callback2;
1032
1033 out.rv = trans1.Start(&request_, callback1.callback(), log_);
1034 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1035 out.rv = trans2.Start(&request_, callback2.callback(), log_);
1036 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1037
1038 out.rv = callback1.WaitForResult();
1039 ASSERT_THAT(out.rv, IsOk());
1040 out.rv = callback2.WaitForResult();
1041 ASSERT_THAT(out.rv, IsOk());
1042
1043 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1044 EXPECT_TRUE(response1->headers);
1045 EXPECT_TRUE(response1->was_fetched_via_spdy);
1046 out.status_line = response1->headers->GetStatusLine();
1047 out.response_info = *response1;
1048 out.rv = ReadTransaction(&trans1, &out.response_data);
1049 EXPECT_THAT(out.rv, IsOk());
1050 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1051 EXPECT_EQ("hello!hello!", out.response_data);
1052
1053 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1054 EXPECT_TRUE(response2->headers);
1055 EXPECT_TRUE(response2->was_fetched_via_spdy);
1056 out.status_line = response2->headers->GetStatusLine();
1057 out.response_info = *response2;
1058 out.rv = ReadTransaction(&trans2, &out.response_data);
1059 EXPECT_THAT(out.rv, IsOk());
1060 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1061 EXPECT_EQ("hello!hello!", out.response_data);
1062
1063 helper.VerifyDataConsumed();
1064 }
1065
TEST_P(SpdyNetworkTransactionTest,TwoGetsLateBindingFromPreconnect)1066 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1067 spdy::SpdySerializedFrame req(
1068 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1069 spdy::SpdySerializedFrame resp(
1070 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1071 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1072 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
1073
1074 spdy::SpdySerializedFrame req2(
1075 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1076 spdy::SpdySerializedFrame resp2(
1077 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1078 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1079 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
1080
1081 MockWrite writes[] = {
1082 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
1083 };
1084 MockRead reads[] = {
1085 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1086 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
1087 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
1088 MockRead(ASYNC, 0, 8), // EOF
1089 };
1090 SequencedSocketData preconnect_data(reads, writes);
1091
1092 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1093
1094 SequencedSocketData data_placeholder;
1095 data_placeholder.set_connect_data(never_finishing_connect);
1096
1097 TransactionHelperResult out;
1098 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1099 helper.RunPreTestSetup();
1100 helper.AddData(&preconnect_data);
1101 // We require placeholder data because 3 connections are attempted (first is
1102 // the preconnect, 2nd and 3rd are the never finished connections.
1103 helper.AddData(&data_placeholder);
1104 helper.AddData(&data_placeholder);
1105
1106 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1107 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1108
1109 TestCompletionCallback callback1;
1110 TestCompletionCallback callback2;
1111
1112 // Preconnect the first.
1113 HttpStreamFactory* http_stream_factory =
1114 helper.session()->http_stream_factory();
1115
1116 http_stream_factory->PreconnectStreams(1, request_);
1117
1118 out.rv = trans1.Start(&request_, callback1.callback(), log_);
1119 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1120 out.rv = trans2.Start(&request_, callback2.callback(), log_);
1121 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1122
1123 out.rv = callback1.WaitForResult();
1124 ASSERT_THAT(out.rv, IsOk());
1125 out.rv = callback2.WaitForResult();
1126 ASSERT_THAT(out.rv, IsOk());
1127
1128 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1129 EXPECT_TRUE(response1->headers);
1130 EXPECT_TRUE(response1->was_fetched_via_spdy);
1131 out.status_line = response1->headers->GetStatusLine();
1132 out.response_info = *response1;
1133 out.rv = ReadTransaction(&trans1, &out.response_data);
1134 EXPECT_THAT(out.rv, IsOk());
1135 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1136 EXPECT_EQ("hello!hello!", out.response_data);
1137
1138 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1139 EXPECT_TRUE(response2->headers);
1140 EXPECT_TRUE(response2->was_fetched_via_spdy);
1141 out.status_line = response2->headers->GetStatusLine();
1142 out.response_info = *response2;
1143 out.rv = ReadTransaction(&trans2, &out.response_data);
1144 EXPECT_THAT(out.rv, IsOk());
1145 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1146 EXPECT_EQ("hello!hello!", out.response_data);
1147
1148 helper.VerifyDataConsumed();
1149 }
1150
1151 // Similar to ThreeGets above, however this test adds a SETTINGS
1152 // frame. The SETTINGS frame is read during the IO loop waiting on
1153 // the first transaction completion, and sets a maximum concurrent
1154 // stream limit of 1. This means that our IO loop exists after the
1155 // second transaction completes, so we can assert on read_index().
TEST_P(SpdyNetworkTransactionTest,ThreeGetsWithMaxConcurrent)1156 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1157 // Construct the request.
1158 // Each request fully completes before the next starts.
1159 spdy::SpdySerializedFrame req(
1160 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1161 spdy::SpdySerializedFrame resp(
1162 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1163 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1164 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
1165 spdy_util_.UpdateWithStreamDestruction(1);
1166
1167 spdy::SpdySerializedFrame req2(
1168 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1169 spdy::SpdySerializedFrame resp2(
1170 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1171 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1172 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
1173 spdy_util_.UpdateWithStreamDestruction(3);
1174
1175 spdy::SpdySerializedFrame req3(
1176 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST));
1177 spdy::SpdySerializedFrame resp3(
1178 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
1179 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
1180 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
1181
1182 spdy::SettingsMap settings;
1183 const uint32_t max_concurrent_streams = 1;
1184 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1185 spdy::SpdySerializedFrame settings_frame(
1186 spdy_util_.ConstructSpdySettings(settings));
1187 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
1188
1189 MockWrite writes[] = {
1190 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1191 CreateMockWrite(req2, 6), CreateMockWrite(req3, 10),
1192 };
1193
1194 MockRead reads[] = {
1195 CreateMockRead(settings_frame, 1),
1196 CreateMockRead(resp, 2),
1197 CreateMockRead(body, 3),
1198 CreateMockRead(fbody, 4),
1199 CreateMockRead(resp2, 7),
1200 CreateMockRead(body2, 8),
1201 CreateMockRead(fbody2, 9),
1202 CreateMockRead(resp3, 11),
1203 CreateMockRead(body3, 12),
1204 CreateMockRead(fbody3, 13),
1205
1206 MockRead(ASYNC, 0, 14), // EOF
1207 };
1208
1209 SequencedSocketData data(reads, writes);
1210
1211 TransactionHelperResult out;
1212 {
1213 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
1214 nullptr);
1215 helper.RunPreTestSetup();
1216 helper.AddData(&data);
1217 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1218 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1219 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1220
1221 TestCompletionCallback callback1;
1222 TestCompletionCallback callback2;
1223 TestCompletionCallback callback3;
1224
1225 out.rv = trans1.Start(&request_, callback1.callback(), log_);
1226 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1227 // Run transaction 1 through quickly to force a read of our SETTINGS
1228 // frame.
1229 out.rv = callback1.WaitForResult();
1230 ASSERT_THAT(out.rv, IsOk());
1231
1232 out.rv = trans2.Start(&request_, callback2.callback(), log_);
1233 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1234 out.rv = trans3.Start(&request_, callback3.callback(), log_);
1235 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1236 out.rv = callback2.WaitForResult();
1237 ASSERT_THAT(out.rv, IsOk());
1238
1239 out.rv = callback3.WaitForResult();
1240 ASSERT_THAT(out.rv, IsOk());
1241
1242 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1243 ASSERT_TRUE(response1);
1244 EXPECT_TRUE(response1->headers);
1245 EXPECT_TRUE(response1->was_fetched_via_spdy);
1246 out.status_line = response1->headers->GetStatusLine();
1247 out.response_info = *response1;
1248 out.rv = ReadTransaction(&trans1, &out.response_data);
1249 EXPECT_THAT(out.rv, IsOk());
1250 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1251 EXPECT_EQ("hello!hello!", out.response_data);
1252
1253 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1254 out.status_line = response2->headers->GetStatusLine();
1255 out.response_info = *response2;
1256 out.rv = ReadTransaction(&trans2, &out.response_data);
1257 EXPECT_THAT(out.rv, IsOk());
1258 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1259 EXPECT_EQ("hello!hello!", out.response_data);
1260
1261 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
1262 out.status_line = response3->headers->GetStatusLine();
1263 out.response_info = *response3;
1264 out.rv = ReadTransaction(&trans3, &out.response_data);
1265 EXPECT_THAT(out.rv, IsOk());
1266 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1267 EXPECT_EQ("hello!hello!", out.response_data);
1268
1269 helper.VerifyDataConsumed();
1270 }
1271 EXPECT_THAT(out.rv, IsOk());
1272 }
1273
1274 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1275 // a fourth transaction. The third and fourth transactions have
1276 // different data ("hello!" vs "hello!hello!") and because of the
1277 // user specified priority, we expect to see them inverted in
1278 // the response from the server.
TEST_P(SpdyNetworkTransactionTest,FourGetsWithMaxConcurrentPriority)1279 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1280 // Construct the request.
1281 spdy::SpdySerializedFrame req(
1282 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1283 spdy::SpdySerializedFrame resp(
1284 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1285 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1286 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
1287 spdy_util_.UpdateWithStreamDestruction(1);
1288
1289 spdy::SpdySerializedFrame req2(
1290 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1291 spdy::SpdySerializedFrame resp2(
1292 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1293 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1294 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
1295 spdy_util_.UpdateWithStreamDestruction(3);
1296
1297 spdy::SpdySerializedFrame req4(
1298 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST));
1299 spdy::SpdySerializedFrame resp4(
1300 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
1301 spdy::SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
1302 spdy_util_.UpdateWithStreamDestruction(5);
1303
1304 spdy::SpdySerializedFrame req3(
1305 spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST));
1306 spdy::SpdySerializedFrame resp3(
1307 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7));
1308 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
1309 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
1310
1311 spdy::SettingsMap settings;
1312 const uint32_t max_concurrent_streams = 1;
1313 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1314 spdy::SpdySerializedFrame settings_frame(
1315 spdy_util_.ConstructSpdySettings(settings));
1316 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
1317 MockWrite writes[] = {
1318 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1319 // By making these synchronous, it guarantees that they are not *started*
1320 // before their sequence number, which in turn verifies that only a single
1321 // request is in-flight at a time.
1322 CreateMockWrite(req2, 6, SYNCHRONOUS),
1323 CreateMockWrite(req4, 10, SYNCHRONOUS),
1324 CreateMockWrite(req3, 13, SYNCHRONOUS),
1325 };
1326 MockRead reads[] = {
1327 CreateMockRead(settings_frame, 1),
1328 CreateMockRead(resp, 2),
1329 CreateMockRead(body, 3),
1330 CreateMockRead(fbody, 4),
1331 CreateMockRead(resp2, 7),
1332 CreateMockRead(body2, 8),
1333 CreateMockRead(fbody2, 9),
1334 CreateMockRead(resp4, 11),
1335 CreateMockRead(fbody4, 12),
1336 CreateMockRead(resp3, 14),
1337 CreateMockRead(body3, 15),
1338 CreateMockRead(fbody3, 16),
1339
1340 MockRead(ASYNC, 0, 17), // EOF
1341 };
1342 SequencedSocketData data(reads, writes);
1343 TransactionHelperResult out;
1344 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1345 helper.RunPreTestSetup();
1346 helper.AddData(&data);
1347
1348 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1349 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1350 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1351 HttpNetworkTransaction trans4(HIGHEST, helper.session());
1352
1353 TestCompletionCallback callback1;
1354 TestCompletionCallback callback2;
1355 TestCompletionCallback callback3;
1356 TestCompletionCallback callback4;
1357
1358 out.rv = trans1.Start(&request_, callback1.callback(), log_);
1359 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1360 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1361 out.rv = callback1.WaitForResult();
1362 ASSERT_THAT(out.rv, IsOk());
1363
1364 // Finish async network reads and writes associated with |trans1|.
1365 base::RunLoop().RunUntilIdle();
1366
1367 out.rv = trans2.Start(&request_, callback2.callback(), log_);
1368 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1369 out.rv = trans3.Start(&request_, callback3.callback(), log_);
1370 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1371 out.rv = trans4.Start(&request_, callback4.callback(), log_);
1372 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
1373
1374 out.rv = callback2.WaitForResult();
1375 ASSERT_THAT(out.rv, IsOk());
1376
1377 out.rv = callback3.WaitForResult();
1378 ASSERT_THAT(out.rv, IsOk());
1379
1380 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1381 EXPECT_TRUE(response1->headers);
1382 EXPECT_TRUE(response1->was_fetched_via_spdy);
1383 out.status_line = response1->headers->GetStatusLine();
1384 out.response_info = *response1;
1385 out.rv = ReadTransaction(&trans1, &out.response_data);
1386 EXPECT_THAT(out.rv, IsOk());
1387 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1388 EXPECT_EQ("hello!hello!", out.response_data);
1389
1390 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1391 out.status_line = response2->headers->GetStatusLine();
1392 out.response_info = *response2;
1393 out.rv = ReadTransaction(&trans2, &out.response_data);
1394 EXPECT_THAT(out.rv, IsOk());
1395 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1396 EXPECT_EQ("hello!hello!", out.response_data);
1397
1398 // notice: response3 gets two hellos, response4 gets one
1399 // hello, so we know dequeuing priority was respected.
1400 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
1401 out.status_line = response3->headers->GetStatusLine();
1402 out.response_info = *response3;
1403 out.rv = ReadTransaction(&trans3, &out.response_data);
1404 EXPECT_THAT(out.rv, IsOk());
1405 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1406 EXPECT_EQ("hello!hello!", out.response_data);
1407
1408 out.rv = callback4.WaitForResult();
1409 EXPECT_THAT(out.rv, IsOk());
1410 const HttpResponseInfo* response4 = trans4.GetResponseInfo();
1411 out.status_line = response4->headers->GetStatusLine();
1412 out.response_info = *response4;
1413 out.rv = ReadTransaction(&trans4, &out.response_data);
1414 EXPECT_THAT(out.rv, IsOk());
1415 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1416 EXPECT_EQ("hello!", out.response_data);
1417 helper.VerifyDataConsumed();
1418 EXPECT_THAT(out.rv, IsOk());
1419 }
1420
1421 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1422 // deletes a session in the middle of the transaction to ensure
1423 // that we properly remove pendingcreatestream objects from
1424 // the spdy_session
TEST_P(SpdyNetworkTransactionTest,ThreeGetsWithMaxConcurrentDelete)1425 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1426 // Construct the request.
1427 spdy::SpdySerializedFrame req(
1428 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1429 spdy::SpdySerializedFrame resp(
1430 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1431 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1432 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
1433 spdy_util_.UpdateWithStreamDestruction(1);
1434
1435 spdy::SpdySerializedFrame req2(
1436 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1437 spdy::SpdySerializedFrame resp2(
1438 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1439 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1440 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
1441
1442 spdy::SettingsMap settings;
1443 const uint32_t max_concurrent_streams = 1;
1444 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1445 spdy::SpdySerializedFrame settings_frame(
1446 spdy_util_.ConstructSpdySettings(settings));
1447 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
1448
1449 MockWrite writes[] = {
1450 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1451 CreateMockWrite(req2, 6),
1452 };
1453 MockRead reads[] = {
1454 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1455 CreateMockRead(body, 3), CreateMockRead(fbody, 4),
1456 CreateMockRead(resp2, 7), CreateMockRead(body2, 8),
1457 CreateMockRead(fbody2, 9), MockRead(ASYNC, 0, 10), // EOF
1458 };
1459
1460 SequencedSocketData data(reads, writes);
1461
1462 TransactionHelperResult out;
1463 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1464 helper.RunPreTestSetup();
1465 helper.AddData(&data);
1466 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
1467 helper.session());
1468 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
1469 helper.session());
1470 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
1471 helper.session());
1472
1473 TestCompletionCallback callback1;
1474 TestCompletionCallback callback2;
1475 TestCompletionCallback callback3;
1476
1477 out.rv = trans1->Start(&request_, callback1.callback(), log_);
1478 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1479 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1480 out.rv = callback1.WaitForResult();
1481 ASSERT_THAT(out.rv, IsOk());
1482
1483 out.rv = trans2->Start(&request_, callback2.callback(), log_);
1484 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1485 out.rv = trans3->Start(&request_, callback3.callback(), log_);
1486 trans3.reset();
1487 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1488 out.rv = callback2.WaitForResult();
1489 ASSERT_THAT(out.rv, IsOk());
1490
1491 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1492 ASSERT_TRUE(response1);
1493 EXPECT_TRUE(response1->headers);
1494 EXPECT_TRUE(response1->was_fetched_via_spdy);
1495 out.status_line = response1->headers->GetStatusLine();
1496 out.response_info = *response1;
1497 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1498 EXPECT_THAT(out.rv, IsOk());
1499 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1500 EXPECT_EQ("hello!hello!", out.response_data);
1501
1502 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1503 ASSERT_TRUE(response2);
1504 out.status_line = response2->headers->GetStatusLine();
1505 out.response_info = *response2;
1506 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1507 EXPECT_THAT(out.rv, IsOk());
1508 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1509 EXPECT_EQ("hello!hello!", out.response_data);
1510 helper.VerifyDataConsumed();
1511 EXPECT_THAT(out.rv, IsOk());
1512 }
1513
1514 namespace {
1515
1516 // A helper class that will delete |transaction| on error when the callback is
1517 // invoked.
1518 class KillerCallback : public TestCompletionCallbackBase {
1519 public:
KillerCallback(std::unique_ptr<HttpNetworkTransaction> transaction)1520 explicit KillerCallback(std::unique_ptr<HttpNetworkTransaction> transaction)
1521 : transaction_(std::move(transaction)) {}
1522
1523 ~KillerCallback() override = default;
1524
callback()1525 CompletionOnceCallback callback() {
1526 return base::BindOnce(&KillerCallback::OnComplete, base::Unretained(this));
1527 }
1528
1529 private:
OnComplete(int result)1530 void OnComplete(int result) {
1531 if (result < 0)
1532 transaction_.reset();
1533
1534 SetResult(result);
1535 }
1536
1537 std::unique_ptr<HttpNetworkTransaction> transaction_;
1538 };
1539
1540 } // namespace
1541
1542 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1543 // closes the socket while we have a pending transaction waiting for
1544 // a pending stream creation. http://crbug.com/52901
TEST_P(SpdyNetworkTransactionTest,ThreeGetsWithMaxConcurrentSocketClose)1545 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1546 // Construct the request. Each stream uses a different priority to provide
1547 // more useful failure information if the requests are made in an unexpected
1548 // order.
1549 spdy::SpdySerializedFrame req(
1550 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
1551 spdy::SpdySerializedFrame resp(
1552 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1553 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1554 spdy::SpdySerializedFrame fin_body(
1555 spdy_util_.ConstructSpdyDataFrame(1, true));
1556 spdy_util_.UpdateWithStreamDestruction(1);
1557
1558 spdy::SpdySerializedFrame req2(
1559 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
1560 spdy::SpdySerializedFrame resp2(
1561 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1562
1563 spdy::SettingsMap settings;
1564 const uint32_t max_concurrent_streams = 1;
1565 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1566 spdy::SpdySerializedFrame settings_frame(
1567 spdy_util_.ConstructSpdySettings(settings));
1568 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
1569
1570 MockWrite writes[] = {CreateMockWrite(req, 0),
1571 CreateMockWrite(settings_ack, 6),
1572 CreateMockWrite(req2, 7)};
1573 MockRead reads[] = {
1574 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1575 CreateMockRead(body, 3),
1576 // Delay the request here. For this test to pass, the three HTTP streams
1577 // have to be created in order, but SpdySession doesn't actually guarantee
1578 // that (See note in SpdySession::ProcessPendingStreamRequests). As a
1579 // workaround, delay finishing up the first stream until the second and
1580 // third streams are waiting in the SPDY stream request queue.
1581 MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(fin_body, 5),
1582 CreateMockRead(resp2, 8),
1583 // The exact error does not matter, but some errors, such as
1584 // ERR_CONNECTION_RESET, may trigger a retry, which this test does not
1585 // account for.
1586 MockRead(ASYNC, ERR_SSL_BAD_RECORD_MAC_ALERT, 9), // Abort!
1587 };
1588
1589 SequencedSocketData data(reads, writes);
1590 SequencedSocketData data_placeholder;
1591
1592 TransactionHelperResult out;
1593 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_, nullptr);
1594 helper.RunPreTestSetup();
1595 helper.AddData(&data);
1596 // We require placeholder data because three get requests are sent out, so
1597 // there needs to be three sets of SSL connection data.
1598 helper.AddData(&data_placeholder);
1599 helper.AddData(&data_placeholder);
1600 HttpNetworkTransaction trans1(HIGHEST, helper.session());
1601 HttpNetworkTransaction trans2(MEDIUM, helper.session());
1602 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
1603 helper.session());
1604 auto* trans3_ptr = trans3.get();
1605
1606 TestCompletionCallback callback1;
1607 TestCompletionCallback callback2;
1608 KillerCallback callback3(std::move(trans3));
1609
1610 out.rv = trans1.Start(&request_, callback1.callback(), log_);
1611 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1612 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1613 out.rv = callback1.WaitForResult();
1614 ASSERT_THAT(out.rv, IsOk());
1615
1616 out.rv = trans2.Start(&request_, callback2.callback(), log_);
1617 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1618 out.rv = trans3_ptr->Start(&request_, callback3.callback(), log_);
1619 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1620
1621 // Run until both transactions are in the SpdySession's queue, waiting for the
1622 // final request to complete.
1623 base::RunLoop().RunUntilIdle();
1624 data.Resume();
1625
1626 out.rv = callback3.WaitForResult();
1627 EXPECT_THAT(out.rv, IsError(ERR_SSL_BAD_RECORD_MAC_ALERT));
1628
1629 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1630 ASSERT_TRUE(response1);
1631 EXPECT_TRUE(response1->headers);
1632 EXPECT_TRUE(response1->was_fetched_via_spdy);
1633 out.status_line = response1->headers->GetStatusLine();
1634 out.response_info = *response1;
1635 out.rv = ReadTransaction(&trans1, &out.response_data);
1636 EXPECT_THAT(out.rv, IsOk());
1637
1638 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1639 ASSERT_TRUE(response2);
1640 out.status_line = response2->headers->GetStatusLine();
1641 out.response_info = *response2;
1642 out.rv = ReadTransaction(&trans2, &out.response_data);
1643 EXPECT_THAT(out.rv, IsError(ERR_SSL_BAD_RECORD_MAC_ALERT));
1644
1645 helper.VerifyDataConsumed();
1646 }
1647
1648 // Test that a simple PUT request works.
TEST_P(SpdyNetworkTransactionTest,Put)1649 TEST_P(SpdyNetworkTransactionTest, Put) {
1650 // Setup the request.
1651 request_.method = "PUT";
1652
1653 spdy::Http2HeaderBlock put_headers(
1654 spdy_util_.ConstructPutHeaderBlock(kDefaultUrl, 0));
1655 spdy::SpdySerializedFrame req(
1656 spdy_util_.ConstructSpdyHeaders(1, std::move(put_headers), LOWEST, true));
1657 MockWrite writes[] = {
1658 CreateMockWrite(req, 0),
1659 };
1660
1661 spdy::SpdySerializedFrame resp(
1662 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1663 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1664 MockRead reads[] = {
1665 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1666 MockRead(ASYNC, 0, 3) // EOF
1667 };
1668
1669 SequencedSocketData data(reads, writes);
1670 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1671 helper.RunToCompletion(&data);
1672 TransactionHelperResult out = helper.output();
1673
1674 EXPECT_THAT(out.rv, IsOk());
1675 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1676 }
1677
1678 // Test that a simple HEAD request works.
TEST_P(SpdyNetworkTransactionTest,Head)1679 TEST_P(SpdyNetworkTransactionTest, Head) {
1680 // Setup the request.
1681 request_.method = "HEAD";
1682
1683 spdy::Http2HeaderBlock head_headers(
1684 spdy_util_.ConstructHeadHeaderBlock(kDefaultUrl, 0));
1685 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyHeaders(
1686 1, std::move(head_headers), LOWEST, true));
1687 MockWrite writes[] = {
1688 CreateMockWrite(req, 0),
1689 };
1690
1691 spdy::SpdySerializedFrame resp(
1692 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1693 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1694 MockRead reads[] = {
1695 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1696 MockRead(ASYNC, 0, 3) // EOF
1697 };
1698
1699 SequencedSocketData data(reads, writes);
1700 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1701 helper.RunToCompletion(&data);
1702 TransactionHelperResult out = helper.output();
1703
1704 EXPECT_THAT(out.rv, IsOk());
1705 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1706 }
1707
1708 // Test that a simple POST works.
TEST_P(SpdyNetworkTransactionTest,Post)1709 TEST_P(SpdyNetworkTransactionTest, Post) {
1710 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1711 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
1712 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1713 MockWrite writes[] = {
1714 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
1715 };
1716
1717 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1718 MockRead reads[] = {
1719 CreateMockRead(resp, 2), CreateMockRead(body, 3),
1720 MockRead(ASYNC, 0, 4) // EOF
1721 };
1722
1723 SequencedSocketData data(reads, writes);
1724 UsePostRequest();
1725 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1726 helper.RunToCompletion(&data);
1727 TransactionHelperResult out = helper.output();
1728 EXPECT_THAT(out.rv, IsOk());
1729 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1730 EXPECT_EQ("hello!", out.response_data);
1731 }
1732
1733 // Test that a POST with a file works.
TEST_P(SpdyNetworkTransactionTest,FilePost)1734 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1735 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1736 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
1737 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1738 MockWrite writes[] = {
1739 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
1740 };
1741
1742 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1743 MockRead reads[] = {
1744 CreateMockRead(resp, 2), CreateMockRead(body, 3),
1745 MockRead(ASYNC, 0, 4) // EOF
1746 };
1747
1748 SequencedSocketData data(reads, writes);
1749 UseFilePostRequest();
1750 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1751 helper.RunToCompletion(&data);
1752 TransactionHelperResult out = helper.output();
1753 EXPECT_THAT(out.rv, IsOk());
1754 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1755 EXPECT_EQ("hello!", out.response_data);
1756 }
1757
1758 // Test that a POST with a unreadable file fails.
TEST_P(SpdyNetworkTransactionTest,UnreadableFilePost)1759 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1760 MockWrite writes[] = {
1761 MockWrite(ASYNC, 0, 0) // EOF
1762 };
1763 MockRead reads[] = {
1764 MockRead(ASYNC, 0, 1) // EOF
1765 };
1766
1767 SequencedSocketData data(reads, writes);
1768 UseUnreadableFilePostRequest();
1769 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1770 helper.RunPreTestSetup();
1771 helper.AddData(&data);
1772 helper.RunDefaultTest();
1773
1774 base::RunLoop().RunUntilIdle();
1775 helper.VerifyDataNotConsumed();
1776 EXPECT_THAT(helper.output().rv, IsError(ERR_ACCESS_DENIED));
1777 }
1778
1779 // Test that a complex POST works.
TEST_P(SpdyNetworkTransactionTest,ComplexPost)1780 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1781 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1782 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
1783 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1784 MockWrite writes[] = {
1785 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
1786 };
1787
1788 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1789 MockRead reads[] = {
1790 CreateMockRead(resp, 2), CreateMockRead(body, 3),
1791 MockRead(ASYNC, 0, 4) // EOF
1792 };
1793
1794 SequencedSocketData data(reads, writes);
1795 UseComplexPostRequest();
1796 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1797 helper.RunToCompletion(&data);
1798 TransactionHelperResult out = helper.output();
1799 EXPECT_THAT(out.rv, IsOk());
1800 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1801 EXPECT_EQ("hello!", out.response_data);
1802 }
1803
1804 // Test that a chunked POST works.
TEST_P(SpdyNetworkTransactionTest,ChunkedPost)1805 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1806 spdy::SpdySerializedFrame req(
1807 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1808 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1809 MockWrite writes[] = {
1810 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
1811 };
1812
1813 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1814 MockRead reads[] = {
1815 CreateMockRead(resp, 2), CreateMockRead(body, 3),
1816 MockRead(ASYNC, 0, 4) // EOF
1817 };
1818
1819 SequencedSocketData data(reads, writes);
1820 UseChunkedPostRequest();
1821 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1822
1823 // These chunks get merged into a single frame when being sent.
1824 const int kFirstChunkSize = kUploadDataSize/2;
1825 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1826 upload_chunked_data_stream()->AppendData(
1827 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1828
1829 helper.RunToCompletion(&data);
1830 TransactionHelperResult out = helper.output();
1831 EXPECT_THAT(out.rv, IsOk());
1832 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1833 EXPECT_EQ(kUploadData, out.response_data);
1834 }
1835
1836 // Test that a chunked POST works with chunks appended after transaction starts.
TEST_P(SpdyNetworkTransactionTest,DelayedChunkedPost)1837 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1838 spdy::SpdySerializedFrame req(
1839 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1840 spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
1841 spdy::SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
1842 spdy::SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
1843 MockWrite writes[] = {
1844 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
1845 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
1846 };
1847
1848 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1849 MockRead reads[] = {
1850 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
1851 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
1852 MockRead(ASYNC, 0, 8) // EOF
1853 };
1854
1855 SequencedSocketData data(reads, writes);
1856 UseChunkedPostRequest();
1857 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1858
1859 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1860
1861 helper.RunPreTestSetup();
1862 helper.AddData(&data);
1863 ASSERT_TRUE(helper.StartDefaultTest());
1864
1865 base::RunLoop().RunUntilIdle();
1866 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1867 base::RunLoop().RunUntilIdle();
1868 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
1869
1870 helper.FinishDefaultTest();
1871 helper.VerifyDataConsumed();
1872
1873 std::string expected_response;
1874 expected_response += kUploadData;
1875 expected_response += kUploadData;
1876 expected_response += kUploadData;
1877
1878 TransactionHelperResult out = helper.output();
1879 EXPECT_THAT(out.rv, IsOk());
1880 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1881 EXPECT_EQ(expected_response, out.response_data);
1882 }
1883
1884 // Test that a POST without any post data works.
TEST_P(SpdyNetworkTransactionTest,NullPost)1885 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1886 // Setup the request.
1887 request_.method = "POST";
1888 // Create an empty UploadData.
1889 request_.upload_data_stream = nullptr;
1890
1891 // When request.upload_data_stream is NULL for post, content-length is
1892 // expected to be 0.
1893 spdy::Http2HeaderBlock req_block(
1894 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
1895 spdy::SpdySerializedFrame req(
1896 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
1897
1898 MockWrite writes[] = {
1899 CreateMockWrite(req, 0),
1900 };
1901
1902 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1903 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1904 MockRead reads[] = {
1905 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1906 MockRead(ASYNC, 0, 3) // EOF
1907 };
1908
1909 SequencedSocketData data(reads, writes);
1910
1911 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1912 helper.RunToCompletion(&data);
1913 TransactionHelperResult out = helper.output();
1914 EXPECT_THAT(out.rv, IsOk());
1915 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1916 EXPECT_EQ("hello!", out.response_data);
1917 }
1918
1919 // Test that a simple POST works.
TEST_P(SpdyNetworkTransactionTest,EmptyPost)1920 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1921 // Create an empty UploadDataStream.
1922 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
1923 ElementsUploadDataStream stream(std::move(element_readers), 0);
1924
1925 // Setup the request.
1926 request_.method = "POST";
1927 request_.upload_data_stream = &stream;
1928
1929 const uint64_t kContentLength = 0;
1930
1931 spdy::Http2HeaderBlock req_block(
1932 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kContentLength));
1933 spdy::SpdySerializedFrame req(
1934 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
1935
1936 MockWrite writes[] = {
1937 CreateMockWrite(req, 0),
1938 };
1939
1940 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1941 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1942 MockRead reads[] = {
1943 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1944 MockRead(ASYNC, 0, 3) // EOF
1945 };
1946
1947 SequencedSocketData data(reads, writes);
1948
1949 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1950 helper.RunToCompletion(&data);
1951 TransactionHelperResult out = helper.output();
1952 EXPECT_THAT(out.rv, IsOk());
1953 EXPECT_EQ("HTTP/1.1 200", out.status_line);
1954 EXPECT_EQ("hello!", out.response_data);
1955 }
1956
1957 // While we're doing a post, the server sends the reply before upload completes.
TEST_P(SpdyNetworkTransactionTest,ResponseBeforePostCompletes)1958 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
1959 spdy::SpdySerializedFrame req(
1960 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1961 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1962 MockWrite writes[] = {
1963 CreateMockWrite(req, 0), CreateMockWrite(body, 3),
1964 };
1965 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1966 MockRead reads[] = {
1967 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1968 MockRead(ASYNC, 0, 4) // EOF
1969 };
1970
1971 // Write the request headers, and read the complete response
1972 // while still waiting for chunked request data.
1973 SequencedSocketData data(reads, writes);
1974 UseChunkedPostRequest();
1975 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
1976 helper.RunPreTestSetup();
1977 helper.AddData(&data);
1978
1979 ASSERT_TRUE(helper.StartDefaultTest());
1980
1981 base::RunLoop().RunUntilIdle();
1982
1983 // Process the request headers, response headers, and response body.
1984 // The request body is still in flight.
1985 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
1986 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1987
1988 // Finish sending the request body.
1989 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
1990 helper.WaitForCallbackToComplete();
1991 EXPECT_THAT(helper.output().rv, IsOk());
1992
1993 std::string response_body;
1994 EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
1995 EXPECT_EQ(kUploadData, response_body);
1996
1997 // Finish async network reads/writes.
1998 base::RunLoop().RunUntilIdle();
1999 helper.VerifyDataConsumed();
2000 }
2001
2002 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2003 // socket causes the TCP write to return zero. This test checks that the client
2004 // tries to queue up the RST_STREAM frame again.
TEST_P(SpdyNetworkTransactionTest,SocketWriteReturnsZero)2005 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2006 spdy::SpdySerializedFrame req(
2007 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2008 spdy::SpdySerializedFrame rst(
2009 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
2010 MockWrite writes[] = {
2011 CreateMockWrite(req, 0, SYNCHRONOUS),
2012 MockWrite(SYNCHRONOUS, nullptr, 0, 2),
2013 CreateMockWrite(rst, 3, SYNCHRONOUS),
2014 };
2015
2016 spdy::SpdySerializedFrame resp(
2017 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2018 MockRead reads[] = {
2019 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 4) // EOF
2020 };
2021
2022 SequencedSocketData data(reads, writes);
2023 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2024 helper.RunPreTestSetup();
2025 helper.AddData(&data);
2026 helper.StartDefaultTest();
2027 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
2028
2029 helper.WaitForCallbackToComplete();
2030 EXPECT_THAT(helper.output().rv, IsOk());
2031
2032 helper.ResetTrans();
2033 base::RunLoop().RunUntilIdle();
2034
2035 helper.VerifyDataConsumed();
2036 }
2037
2038 // Test that the transaction doesn't crash when we don't have a reply.
TEST_P(SpdyNetworkTransactionTest,ResponseWithoutHeaders)2039 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
2040 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2041 MockRead reads[] = {
2042 CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF
2043 };
2044
2045 spdy::SpdySerializedFrame req(
2046 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2047 spdy::SpdySerializedFrame rst(
2048 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
2049 MockWrite writes[] = {
2050 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
2051 };
2052 SequencedSocketData data(reads, writes);
2053 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2054 helper.RunToCompletion(&data);
2055 TransactionHelperResult out = helper.output();
2056 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
2057 }
2058
2059 // Test that the transaction doesn't crash when we get two replies on the same
2060 // stream ID. See http://crbug.com/45639.
TEST_P(SpdyNetworkTransactionTest,ResponseWithTwoSynReplies)2061 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2062 spdy::SpdySerializedFrame req(
2063 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2064 spdy::SpdySerializedFrame rst(
2065 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
2066 MockWrite writes[] = {
2067 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
2068 };
2069
2070 spdy::SpdySerializedFrame resp0(
2071 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2072 spdy::SpdySerializedFrame resp1(
2073 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2074 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2075 MockRead reads[] = {
2076 CreateMockRead(resp0, 1), CreateMockRead(resp1, 2),
2077 CreateMockRead(body, 3), MockRead(ASYNC, 0, 5) // EOF
2078 };
2079
2080 SequencedSocketData data(reads, writes);
2081
2082 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2083 helper.RunPreTestSetup();
2084 helper.AddData(&data);
2085
2086 HttpNetworkTransaction* trans = helper.trans();
2087
2088 TestCompletionCallback callback;
2089 int rv = trans->Start(&request_, callback.callback(), log_);
2090 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2091 rv = callback.WaitForResult();
2092 EXPECT_THAT(rv, IsOk());
2093
2094 const HttpResponseInfo* response = trans->GetResponseInfo();
2095 ASSERT_TRUE(response);
2096 EXPECT_TRUE(response->headers);
2097 EXPECT_TRUE(response->was_fetched_via_spdy);
2098 std::string response_data;
2099 rv = ReadTransaction(trans, &response_data);
2100 EXPECT_THAT(rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
2101
2102 helper.VerifyDataConsumed();
2103 }
2104
TEST_P(SpdyNetworkTransactionTest,ResetReplyWithTransferEncoding)2105 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2106 // Construct the request.
2107 spdy::SpdySerializedFrame req(
2108 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2109 spdy::SpdySerializedFrame rst(
2110 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
2111 MockWrite writes[] = {
2112 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
2113 };
2114
2115 const char* const headers[] = {
2116 "transfer-encoding", "chunked"
2117 };
2118 spdy::SpdySerializedFrame resp(
2119 spdy_util_.ConstructSpdyGetReply(headers, 1, 1));
2120 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2121 MockRead reads[] = {
2122 CreateMockRead(resp, 1), CreateMockRead(body, 3),
2123 MockRead(ASYNC, 0, 4) // EOF
2124 };
2125
2126 SequencedSocketData data(reads, writes);
2127 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2128 helper.RunToCompletion(&data);
2129 TransactionHelperResult out = helper.output();
2130 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
2131
2132 helper.session()->spdy_session_pool()->CloseAllSessions();
2133 helper.VerifyDataConsumed();
2134 }
2135
TEST_P(SpdyNetworkTransactionTest,CancelledTransaction)2136 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2137 // Construct the request.
2138 spdy::SpdySerializedFrame req(
2139 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2140 MockWrite writes[] = {
2141 CreateMockWrite(req),
2142 };
2143
2144 spdy::SpdySerializedFrame resp(
2145 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2146 MockRead reads[] = {
2147 CreateMockRead(resp),
2148 // This following read isn't used by the test, except during the
2149 // RunUntilIdle() call at the end since the SpdySession survives the
2150 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2151 // MockRead will do here.
2152 MockRead(ASYNC, 0, 0) // EOF
2153 };
2154
2155 StaticSocketDataProvider data(reads, writes);
2156
2157 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2158 helper.RunPreTestSetup();
2159 helper.AddData(&data);
2160 HttpNetworkTransaction* trans = helper.trans();
2161
2162 TestCompletionCallback callback;
2163 int rv = trans->Start(&request_, callback.callback(), log_);
2164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2165 helper.ResetTrans(); // Cancel the transaction.
2166
2167 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2168 // MockClientSocketFactory) are still alive.
2169 base::RunLoop().RunUntilIdle();
2170 helper.VerifyDataNotConsumed();
2171 }
2172
2173 // Verify that the client sends a Rst Frame upon cancelling the stream.
TEST_P(SpdyNetworkTransactionTest,CancelledTransactionSendRst)2174 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2175 spdy::SpdySerializedFrame req(
2176 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2177 spdy::SpdySerializedFrame rst(
2178 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
2179 MockWrite writes[] = {
2180 CreateMockWrite(req, 0, SYNCHRONOUS),
2181 CreateMockWrite(rst, 2, SYNCHRONOUS),
2182 };
2183
2184 spdy::SpdySerializedFrame resp(
2185 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2186 MockRead reads[] = {
2187 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 3) // EOF
2188 };
2189
2190 SequencedSocketData data(reads, writes);
2191
2192 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2193 helper.RunPreTestSetup();
2194 helper.AddData(&data);
2195 HttpNetworkTransaction* trans = helper.trans();
2196
2197 TestCompletionCallback callback;
2198
2199 int rv = trans->Start(&request_, callback.callback(), log_);
2200 EXPECT_THAT(callback.GetResult(rv), IsOk());
2201
2202 helper.ResetTrans();
2203 base::RunLoop().RunUntilIdle();
2204
2205 helper.VerifyDataConsumed();
2206 }
2207
2208 // Verify that the client can correctly deal with the user callback attempting
2209 // to start another transaction on a session that is closing down. See
2210 // http://crbug.com/47455
TEST_P(SpdyNetworkTransactionTest,StartTransactionOnReadCallback)2211 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2212 spdy::SpdySerializedFrame req(
2213 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2214 MockWrite writes[] = {CreateMockWrite(req)};
2215 MockWrite writes2[] = {CreateMockWrite(req, 0),
2216 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3)};
2217
2218 // The indicated length of this frame is longer than its actual length. When
2219 // the session receives an empty frame after this one, it shuts down the
2220 // session, and calls the read callback with the incomplete data.
2221 const uint8_t kGetBodyFrame2[] = {
2222 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2223 0x07, 'h', 'e', 'l', 'l', 'o', '!',
2224 };
2225
2226 spdy::SpdySerializedFrame resp(
2227 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2228 MockRead reads[] = {
2229 CreateMockRead(resp, 1),
2230 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2231 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2232 std::size(kGetBodyFrame2), 3),
2233 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2234 MockRead(ASYNC, nullptr, 0, 5), // EOF
2235 };
2236 MockRead reads2[] = {
2237 CreateMockRead(resp, 1), MockRead(ASYNC, nullptr, 0, 2), // EOF
2238 };
2239
2240 SequencedSocketData data(reads, writes);
2241 SequencedSocketData data2(reads2, writes2);
2242
2243 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2244 helper.RunPreTestSetup();
2245 helper.AddData(&data);
2246 helper.AddData(&data2);
2247 HttpNetworkTransaction* trans = helper.trans();
2248
2249 // Start the transaction with basic parameters.
2250 TestCompletionCallback callback;
2251 int rv = trans->Start(&request_, callback.callback(), log_);
2252 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2253 rv = callback.WaitForResult();
2254
2255 const int kSize = 3000;
2256 auto buf = base::MakeRefCounted<IOBufferWithSize>(kSize);
2257 rv = trans->Read(
2258 buf.get(), kSize,
2259 base::BindOnce(&SpdyNetworkTransactionTest::StartTransactionCallback,
2260 helper.session(), default_url_, log_));
2261 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
2262 // This forces an err_IO_pending, which sets the callback.
2263 data.Resume();
2264 data.RunUntilPaused();
2265
2266 // This finishes the read.
2267 data.Resume();
2268 base::RunLoop().RunUntilIdle();
2269 helper.VerifyDataConsumed();
2270 }
2271
2272 // Verify that the client can correctly deal with the user callback deleting
2273 // the transaction. Failures will usually be flagged by thread and/or memory
2274 // checking tools. See http://crbug.com/46925
TEST_P(SpdyNetworkTransactionTest,DeleteSessionOnReadCallback)2275 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2276 spdy::SpdySerializedFrame req(
2277 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2278 MockWrite writes[] = {CreateMockWrite(req, 0)};
2279
2280 spdy::SpdySerializedFrame resp(
2281 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2282 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2283 MockRead reads[] = {
2284 CreateMockRead(resp, 1),
2285 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2286 CreateMockRead(body, 3), MockRead(ASYNC, nullptr, 0, 4), // EOF
2287 };
2288
2289 SequencedSocketData data(reads, writes);
2290
2291 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2292 helper.RunPreTestSetup();
2293 helper.AddData(&data);
2294 HttpNetworkTransaction* trans = helper.trans();
2295
2296 // Start the transaction with basic parameters.
2297 TestCompletionCallback callback;
2298 int rv = trans->Start(&request_, callback.callback(), log_);
2299 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2300 rv = callback.WaitForResult();
2301
2302 // Setup a user callback which will delete the session, and clear out the
2303 // memory holding the stream object. Note that the callback deletes trans.
2304 const int kSize = 3000;
2305 auto buf = base::MakeRefCounted<IOBufferWithSize>(kSize);
2306 rv = trans->Read(
2307 buf.get(), kSize,
2308 base::BindOnce(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2309 base::Unretained(&helper)));
2310 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
2311 data.Resume();
2312
2313 // Finish running rest of tasks.
2314 base::RunLoop().RunUntilIdle();
2315 helper.VerifyDataConsumed();
2316 }
2317
TEST_P(SpdyNetworkTransactionTest,RedirectGetRequest)2318 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2319 MockClientSocketFactory socket_factory;
2320 auto context_builder =
2321 CreateSpdyTestURLRequestContextBuilder(&socket_factory);
2322 auto spdy_url_request_context = context_builder->Build();
2323 SpdySessionPoolPeer pool_peer(
2324 spdy_url_request_context->http_transaction_factory()
2325 ->GetSession()
2326 ->spdy_session_pool());
2327 pool_peer.SetEnableSendingInitialData(false);
2328 // Use a different port to avoid trying to reuse the initial H2 session.
2329 const char kRedirectUrl[] = "https://www.foo.com:8080/index.php";
2330
2331 SSLSocketDataProvider ssl_provider0(ASYNC, OK);
2332 ssl_provider0.next_proto = kProtoHTTP2;
2333 socket_factory.AddSSLSocketDataProvider(&ssl_provider0);
2334
2335 spdy::Http2HeaderBlock headers0(
2336 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2337 headers0["user-agent"] = "";
2338 headers0["accept-encoding"] = "gzip, deflate";
2339
2340 spdy::SpdySerializedFrame req0(
2341 spdy_util_.ConstructSpdyHeaders(1, std::move(headers0), LOWEST, true));
2342 spdy::SpdySerializedFrame rst(
2343 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
2344 MockWrite writes0[] = {CreateMockWrite(req0, 0), CreateMockWrite(rst, 2)};
2345
2346 const char* const kExtraHeaders[] = {"location", kRedirectUrl};
2347 spdy::SpdySerializedFrame resp0(spdy_util_.ConstructSpdyReplyError(
2348 "301", kExtraHeaders, std::size(kExtraHeaders) / 2, 1));
2349 MockRead reads0[] = {CreateMockRead(resp0, 1), MockRead(ASYNC, 0, 3)};
2350
2351 SequencedSocketData data0(reads0, writes0);
2352 socket_factory.AddSocketDataProvider(&data0);
2353
2354 SSLSocketDataProvider ssl_provider1(ASYNC, OK);
2355 ssl_provider1.next_proto = kProtoHTTP2;
2356 socket_factory.AddSSLSocketDataProvider(&ssl_provider1);
2357
2358 SpdyTestUtil spdy_util1(/*use_priority_header=*/true);
2359 spdy::Http2HeaderBlock headers1(
2360 spdy_util1.ConstructGetHeaderBlock(kRedirectUrl));
2361 headers1["user-agent"] = "";
2362 headers1["accept-encoding"] = "gzip, deflate";
2363 spdy::SpdySerializedFrame req1(
2364 spdy_util1.ConstructSpdyHeaders(1, std::move(headers1), LOWEST, true));
2365 MockWrite writes1[] = {CreateMockWrite(req1, 0)};
2366
2367 spdy::SpdySerializedFrame resp1(
2368 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
2369 spdy::SpdySerializedFrame body1(spdy_util1.ConstructSpdyDataFrame(1, true));
2370 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2371 MockRead(ASYNC, 0, 3)};
2372
2373 SequencedSocketData data1(reads1, writes1);
2374 socket_factory.AddSocketDataProvider(&data1);
2375
2376 TestDelegate delegate;
2377
2378 std::unique_ptr<URLRequest> request = spdy_url_request_context->CreateRequest(
2379 default_url_, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
2380 request->Start();
2381 delegate.RunUntilRedirect();
2382
2383 EXPECT_EQ(1, delegate.received_redirect_count());
2384
2385 request->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
2386 absl::nullopt /* modified_headers */);
2387 delegate.RunUntilComplete();
2388
2389 EXPECT_EQ(1, delegate.response_started_count());
2390 EXPECT_FALSE(delegate.received_data_before_response());
2391 EXPECT_THAT(delegate.request_status(), IsOk());
2392 EXPECT_EQ("hello!", delegate.data_received());
2393
2394 // Pump the message loop to allow read data to be consumed.
2395 base::RunLoop().RunUntilIdle();
2396
2397 EXPECT_TRUE(data0.AllReadDataConsumed());
2398 EXPECT_TRUE(data0.AllWriteDataConsumed());
2399 EXPECT_TRUE(data1.AllReadDataConsumed());
2400 EXPECT_TRUE(data1.AllWriteDataConsumed());
2401 }
2402
TEST_P(SpdyNetworkTransactionTest,RedirectMultipleLocations)2403 TEST_P(SpdyNetworkTransactionTest, RedirectMultipleLocations) {
2404 const spdy::SpdyStreamId kStreamId = 1;
2405 // Construct the request and the RST frame.
2406 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(
2407 /*extra_headers=*/nullptr, /*extra_header_count=*/0, kStreamId, LOWEST));
2408 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
2409 kStreamId, spdy::ERROR_CODE_PROTOCOL_ERROR));
2410 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
2411
2412 // Construct the response.
2413 const char* const kExtraResponseHeaders[] = {
2414 "location",
2415 "https://example1.test",
2416 "location",
2417 "https://example2.test",
2418 };
2419 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
2420 "301", kExtraResponseHeaders, std::size(kExtraResponseHeaders) / 2,
2421 kStreamId));
2422 spdy::SpdySerializedFrame body(
2423 spdy_util_.ConstructSpdyDataFrame(kStreamId, /*fin=*/true));
2424 MockRead reads[] = {
2425 CreateMockRead(resp, 1), CreateMockRead(body, 2),
2426 MockRead(ASYNC, 0, 3) // EOF
2427 };
2428
2429 SequencedSocketData data(reads, writes);
2430 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2431 helper.RunToCompletion(&data);
2432 TransactionHelperResult out = helper.output();
2433 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
2434 }
2435
TEST_P(SpdyNetworkTransactionTest,NoConnectionPoolingOverTunnel)2436 TEST_P(SpdyNetworkTransactionTest, NoConnectionPoolingOverTunnel) {
2437 // Use port 443 for two reasons: This makes the endpoint is port 443 check in
2438 // NormalSpdyTransactionHelper pass, and this means that the tunnel uses the
2439 // same port as the servers, to further confuse things.
2440 const char kPacString[] = "PROXY myproxy:443";
2441
2442 auto session_deps = std::make_unique<SpdySessionDependencies>(
2443 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
2444 kPacString, TRAFFIC_ANNOTATION_FOR_TESTS));
2445 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
2446 std::move(session_deps));
2447
2448 // Only one request uses the first connection.
2449 spdy::SpdySerializedFrame req1(
2450 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
2451 MockWrite writes1[] = {
2452 MockWrite(ASYNC, 0,
2453 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2454 "Host: www.example.org:443\r\n"
2455 "Proxy-Connection: keep-alive\r\n\r\n"),
2456 CreateMockWrite(req1, 2),
2457 };
2458
2459 spdy::SpdySerializedFrame resp1(
2460 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2461 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2462 MockRead reads1[] = {MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
2463 CreateMockRead(resp1, 3), CreateMockRead(body1, 4),
2464 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
2465
2466 MockConnect connect1(ASYNC, OK);
2467 SequencedSocketData data1(connect1, reads1, writes1);
2468
2469 // Run a transaction to completion to set up a SPDY session.
2470 helper.RunToCompletion(&data1);
2471 TransactionHelperResult out = helper.output();
2472 EXPECT_THAT(out.rv, IsOk());
2473 EXPECT_EQ("HTTP/1.1 200", out.status_line);
2474 EXPECT_EQ("hello!", out.response_data);
2475
2476 // A new SPDY session should have been created.
2477 SpdySessionKey key1(HostPortPair("www.example.org", 443),
2478 PacResultElementToProxyChain(kPacString),
2479 PRIVACY_MODE_DISABLED,
2480 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
2481 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2482 base::WeakPtr<SpdySession> session1 =
2483 helper.session()->spdy_session_pool()->FindAvailableSession(
2484 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
2485 NetLogWithSource());
2486 ASSERT_TRUE(session1);
2487
2488 // The second request uses a second connection.
2489 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
2490 spdy::SpdySerializedFrame req2(
2491 spdy_util2.ConstructSpdyGet("https://example.test", 1, LOWEST));
2492 MockWrite writes2[] = {
2493 MockWrite(ASYNC, 0,
2494 "CONNECT example.test:443 HTTP/1.1\r\n"
2495 "Host: example.test:443\r\n"
2496 "Proxy-Connection: keep-alive\r\n\r\n"),
2497 CreateMockWrite(req2, 2),
2498 };
2499
2500 spdy::SpdySerializedFrame resp2(
2501 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
2502 spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true));
2503 MockRead reads2[] = {MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
2504 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
2505 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
2506
2507 MockConnect connect2(ASYNC, OK);
2508 SequencedSocketData data2(connect2, reads2, writes2);
2509 helper.AddData(&data2);
2510
2511 HttpRequestInfo request2;
2512 request2.method = "GET";
2513 request2.url = GURL("https://example.test/");
2514 request2.load_flags = 0;
2515 request2.traffic_annotation =
2516 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2517 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2518 helper.session());
2519
2520 TestCompletionCallback callback;
2521 EXPECT_THAT(trans2->Start(&request2, callback.callback(), NetLogWithSource()),
2522 IsError(ERR_IO_PENDING));
2523
2524 // Wait for the second request to get headers. It should create a new H2
2525 // session to do so.
2526 EXPECT_THAT(callback.WaitForResult(), IsOk());
2527
2528 const HttpResponseInfo* response = trans2->GetResponseInfo();
2529 ASSERT_TRUE(response);
2530 ASSERT_TRUE(response->headers);
2531 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2532 EXPECT_TRUE(response->was_fetched_via_spdy);
2533 EXPECT_TRUE(response->was_alpn_negotiated);
2534 std::string response_data;
2535 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
2536 EXPECT_EQ("hello!", response_data);
2537
2538 // Inspect the new session.
2539 SpdySessionKey key2(HostPortPair("example.test", 443),
2540 PacResultElementToProxyChain(kPacString),
2541 PRIVACY_MODE_DISABLED,
2542 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
2543 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2544 base::WeakPtr<SpdySession> session2 =
2545 helper.session()->spdy_session_pool()->FindAvailableSession(
2546 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
2547 NetLogWithSource());
2548 ASSERT_TRUE(session2);
2549 ASSERT_TRUE(session1);
2550 EXPECT_NE(session1.get(), session2.get());
2551 }
2552
2553 // Check that if a session is found after host resolution, but is closed before
2554 // the task to try to use it executes, the request will continue to create a new
2555 // socket and use it.
TEST_P(SpdyNetworkTransactionTest,ConnectionPoolingSessionClosedBeforeUse)2556 TEST_P(SpdyNetworkTransactionTest, ConnectionPoolingSessionClosedBeforeUse) {
2557 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2558
2559 // Only one request uses the first connection.
2560 spdy::SpdySerializedFrame req1(
2561 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
2562 MockWrite writes1[] = {
2563 CreateMockWrite(req1, 0),
2564 };
2565
2566 spdy::SpdySerializedFrame resp1(
2567 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2568 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2569 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2570 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
2571
2572 MockConnect connect1(ASYNC, OK);
2573 SequencedSocketData data1(connect1, reads1, writes1);
2574
2575 // Run a transaction to completion to set up a SPDY session.
2576 helper.RunToCompletion(&data1);
2577 TransactionHelperResult out = helper.output();
2578 EXPECT_THAT(out.rv, IsOk());
2579 EXPECT_EQ("HTTP/1.1 200", out.status_line);
2580 EXPECT_EQ("hello!", out.response_data);
2581
2582 // A new SPDY session should have been created.
2583 SpdySessionKey key1(HostPortPair("www.example.org", 443),
2584 ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
2585 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
2586 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2587 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
2588 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
2589 NetLogWithSource()));
2590
2591 // The second request uses a second connection.
2592 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
2593 spdy::SpdySerializedFrame req2(
2594 spdy_util2.ConstructSpdyGet("https://example.test", 1, LOWEST));
2595 MockWrite writes2[] = {
2596 CreateMockWrite(req2, 0),
2597 };
2598
2599 spdy::SpdySerializedFrame resp2(
2600 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
2601 spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true));
2602 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
2603 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
2604
2605 MockConnect connect2(ASYNC, OK);
2606 SequencedSocketData data2(connect2, reads2, writes2);
2607 helper.AddData(&data2);
2608
2609 HttpRequestInfo request2;
2610 request2.method = "GET";
2611 request2.url = GURL("https://example.test/");
2612 request2.load_flags = 0;
2613 request2.traffic_annotation =
2614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2615 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2616 helper.session());
2617
2618 // Set on-demand mode and run the second request to the DNS lookup.
2619 helper.session_deps()->host_resolver->set_ondemand_mode(true);
2620 TestCompletionCallback callback;
2621 EXPECT_THAT(trans2->Start(&request2, callback.callback(), NetLogWithSource()),
2622 IsError(ERR_IO_PENDING));
2623 base::RunLoop().RunUntilIdle();
2624 ASSERT_TRUE(helper.session_deps()->host_resolver->has_pending_requests());
2625
2626 // Resolve the request now, which should create an alias for the SpdySession
2627 // immediately, but the task to use the session for the second request should
2628 // run asynchronously, so it hasn't run yet.
2629 helper.session_deps()->host_resolver->ResolveOnlyRequestNow();
2630 SpdySessionKey key2(HostPortPair("example.test", 443), ProxyChain::Direct(),
2631 PRIVACY_MODE_DISABLED,
2632 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
2633 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2634 base::WeakPtr<SpdySession> session1 =
2635 helper.session()->spdy_session_pool()->FindAvailableSession(
2636 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
2637 NetLogWithSource());
2638 ASSERT_TRUE(session1);
2639 EXPECT_EQ(key1, session1->spdy_session_key());
2640 // Remove the session before the second request can try to use it.
2641 helper.session()->spdy_session_pool()->CloseAllSessions();
2642
2643 // Wait for the second request to get headers. It should create a new H2
2644 // session to do so.
2645 EXPECT_THAT(callback.WaitForResult(), IsOk());
2646
2647 const HttpResponseInfo* response = trans2->GetResponseInfo();
2648 ASSERT_TRUE(response);
2649 ASSERT_TRUE(response->headers);
2650 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2651 EXPECT_TRUE(response->was_fetched_via_spdy);
2652 EXPECT_TRUE(response->was_alpn_negotiated);
2653 std::string response_data;
2654 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
2655 EXPECT_EQ("hello!", response_data);
2656
2657 // Inspect the new session.
2658 base::WeakPtr<SpdySession> session2 =
2659 helper.session()->spdy_session_pool()->FindAvailableSession(
2660 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
2661 NetLogWithSource());
2662 ASSERT_TRUE(session2);
2663 EXPECT_EQ(key2, session2->spdy_session_key());
2664 helper.VerifyDataConsumed();
2665 }
2666
2667 #if BUILDFLAG(IS_ANDROID)
2668
2669 // Test this if two HttpNetworkTransactions try to repurpose the same
2670 // SpdySession with two different SocketTags, only one request gets the session,
2671 // while the other makes a new SPDY session.
TEST_P(SpdyNetworkTransactionTest,ConnectionPoolingMultipleSocketTags)2672 TEST_P(SpdyNetworkTransactionTest, ConnectionPoolingMultipleSocketTags) {
2673 const SocketTag kSocketTag1(SocketTag::UNSET_UID, 1);
2674 const SocketTag kSocketTag2(SocketTag::UNSET_UID, 2);
2675 const SocketTag kSocketTag3(SocketTag::UNSET_UID, 3);
2676
2677 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2678
2679 // The first and third requests use the first connection.
2680 spdy::SpdySerializedFrame req1(
2681 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
2682 spdy_util_.UpdateWithStreamDestruction(1);
2683 spdy::SpdySerializedFrame req3(
2684 spdy_util_.ConstructSpdyGet("https://example.test/request3", 3, LOWEST));
2685 MockWrite writes1[] = {
2686 CreateMockWrite(req1, 0),
2687 CreateMockWrite(req3, 3),
2688 };
2689
2690 spdy::SpdySerializedFrame resp1(
2691 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2692 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2693 spdy::SpdySerializedFrame resp3(
2694 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2695 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(3, true));
2696 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2697 CreateMockRead(resp3, 4), CreateMockRead(body3, 5),
2698 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
2699
2700 SequencedSocketData data1(MockConnect(ASYNC, OK), reads1, writes1);
2701 helper.AddData(&data1);
2702
2703 // Due to the vagaries of how the socket pools work, in this particular case,
2704 // the second ConnectJob will be cancelled, but only after it tries to start
2705 // connecting. This does not happen in the general case of a bunch of requests
2706 // using the same socket tag.
2707 SequencedSocketData data2(MockConnect(SYNCHRONOUS, ERR_IO_PENDING),
2708 base::span<const MockRead>(),
2709 base::span<const MockWrite>());
2710 helper.AddData(&data2);
2711
2712 // The second request uses a second connection.
2713 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
2714 spdy::SpdySerializedFrame req2(
2715 spdy_util2.ConstructSpdyGet("https://example.test/request2", 1, LOWEST));
2716 MockWrite writes2[] = {
2717 CreateMockWrite(req2, 0),
2718 };
2719
2720 spdy::SpdySerializedFrame resp2(
2721 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
2722 spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true));
2723 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
2724 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
2725
2726 SequencedSocketData data3(MockConnect(ASYNC, OK), reads2, writes2);
2727 helper.AddData(&data3);
2728
2729 // Run a transaction to completion to set up a SPDY session. This can't use
2730 // RunToCompletion(), since it can't call VerifyDataConsumed() yet.
2731 helper.RunPreTestSetup();
2732 helper.RunDefaultTest();
2733 TransactionHelperResult out = helper.output();
2734 EXPECT_THAT(out.rv, IsOk());
2735 EXPECT_EQ("HTTP/1.1 200", out.status_line);
2736 EXPECT_EQ("hello!", out.response_data);
2737
2738 // A new SPDY session should have been created.
2739 SpdySessionKey key1(HostPortPair("www.example.org", 443),
2740 ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
2741 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
2742 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2743 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
2744 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
2745 NetLogWithSource()));
2746
2747 // Set on-demand mode for the next two requests.
2748 helper.session_deps()->host_resolver->set_ondemand_mode(true);
2749
2750 HttpRequestInfo request2;
2751 request2.socket_tag = kSocketTag2;
2752 request2.method = "GET";
2753 request2.url = GURL("https://example.test/request2");
2754 request2.load_flags = 0;
2755 request2.traffic_annotation =
2756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2757 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2758 helper.session());
2759 TestCompletionCallback callback2;
2760 EXPECT_THAT(
2761 trans2->Start(&request2, callback2.callback(), NetLogWithSource()),
2762 IsError(ERR_IO_PENDING));
2763
2764 HttpRequestInfo request3;
2765 request3.socket_tag = kSocketTag3;
2766 request3.method = "GET";
2767 request3.url = GURL("https://example.test/request3");
2768 request3.load_flags = 0;
2769 request3.traffic_annotation =
2770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2771 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2772 helper.session());
2773 TestCompletionCallback callback3;
2774 EXPECT_THAT(
2775 trans3->Start(&request3, callback3.callback(), NetLogWithSource()),
2776 IsError(ERR_IO_PENDING));
2777
2778 // Run the message loop until both requests are waiting on the host resolver.
2779 base::RunLoop().RunUntilIdle();
2780 ASSERT_TRUE(helper.session_deps()->host_resolver->has_pending_requests());
2781
2782 // Complete the second requests's DNS lookup now, which should create an alias
2783 // for the SpdySession immediately, but the task to use the session for the
2784 // second request should run asynchronously, so it hasn't run yet.
2785 helper.session_deps()->host_resolver->ResolveNow(2);
2786 SpdySessionKey key2(HostPortPair("example.test", 443), ProxyChain::Direct(),
2787 PRIVACY_MODE_DISABLED,
2788 SpdySessionKey::IsProxySession::kFalse, kSocketTag2,
2789 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2790
2791 // Complete the third requests's DNS lookup now, which should hijack the
2792 // SpdySession from the second request.
2793 helper.session_deps()->host_resolver->ResolveNow(3);
2794 SpdySessionKey key3(HostPortPair("example.test", 443), ProxyChain::Direct(),
2795 PRIVACY_MODE_DISABLED,
2796 SpdySessionKey::IsProxySession::kFalse, kSocketTag3,
2797 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2798
2799 // Wait for the second request to get headers. It should create a new H2
2800 // session to do so.
2801 EXPECT_THAT(callback2.WaitForResult(), IsOk());
2802
2803 const HttpResponseInfo* response = trans2->GetResponseInfo();
2804 ASSERT_TRUE(response);
2805 ASSERT_TRUE(response->headers);
2806 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2807 EXPECT_TRUE(response->was_fetched_via_spdy);
2808 EXPECT_TRUE(response->was_alpn_negotiated);
2809 std::string response_data;
2810 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
2811 EXPECT_EQ("hello!", response_data);
2812
2813 // Wait for the third request to get headers. It should have reused the first
2814 // session.
2815 EXPECT_THAT(callback3.WaitForResult(), IsOk());
2816
2817 response = trans3->GetResponseInfo();
2818 ASSERT_TRUE(response);
2819 ASSERT_TRUE(response->headers);
2820 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2821 EXPECT_TRUE(response->was_fetched_via_spdy);
2822 EXPECT_TRUE(response->was_alpn_negotiated);
2823 ASSERT_THAT(ReadTransaction(trans3.get(), &response_data), IsOk());
2824 EXPECT_EQ("hello!", response_data);
2825
2826 helper.VerifyDataConsumed();
2827 }
2828
TEST_P(SpdyNetworkTransactionTest,SocketTagChangeSessionTagWithDnsAliases)2829 TEST_P(SpdyNetworkTransactionTest, SocketTagChangeSessionTagWithDnsAliases) {
2830 SocketTag socket_tag_1(SocketTag::UNSET_UID, 1);
2831 SocketTag socket_tag_2(SocketTag::UNSET_UID, 2);
2832 request_.socket_tag = socket_tag_1;
2833
2834 std::unique_ptr<SpdySessionDependencies> session_deps =
2835 std::make_unique<SpdySessionDependencies>();
2836 std::unique_ptr<MockCachingHostResolver> host_resolver =
2837 std::make_unique<MockCachingHostResolver>(2 /* cache_invalidation_num */);
2838 session_deps->host_resolver = std::move(host_resolver);
2839
2840 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
2841 std::move(session_deps));
2842
2843 GURL url = request_.url;
2844 std::set<std::string> dns_aliases({"alias1", "alias2", "alias3"});
2845 helper.session_deps()->host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
2846 url.host(), "127.0.0.1", dns_aliases);
2847
2848 spdy::SpdySerializedFrame req1(
2849 spdy_util_.ConstructSpdyGet(url.spec().c_str(), 1, DEFAULT_PRIORITY));
2850 spdy_util_.UpdateWithStreamDestruction(1);
2851 spdy::SpdySerializedFrame req2(
2852 spdy_util_.ConstructSpdyGet(url.spec().c_str(), 3, DEFAULT_PRIORITY));
2853 MockWrite writes[] = {
2854 CreateMockWrite(req1, 0),
2855 CreateMockWrite(req2, 3),
2856 };
2857
2858 spdy::SpdySerializedFrame resp1(
2859 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2860 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2861 spdy::SpdySerializedFrame resp2(
2862 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2863 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
2864 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2865 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
2866 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
2867
2868 SequencedSocketData data(MockConnect(ASYNC, OK), reads, writes);
2869 helper.AddData(&data);
2870
2871 // Run a transaction to completion to set up a SPDY session. This can't use
2872 // RunToCompletion(), since it can't call VerifyDataConsumed() yet because
2873 // there are still further requests expected.
2874 helper.RunPreTestSetup();
2875 helper.RunDefaultTest();
2876 TransactionHelperResult out = helper.output();
2877 EXPECT_THAT(out.rv, IsOk());
2878 EXPECT_EQ("HTTP/1.1 200", out.status_line);
2879 EXPECT_EQ("hello!", out.response_data);
2880
2881 // A new SPDY session should have been created.
2882 EXPECT_EQ(1u, helper.GetSpdySessionCount());
2883 SpdySessionKey key1(HostPortPair(url.host(), 443), ProxyChain::Direct(),
2884 PRIVACY_MODE_DISABLED,
2885 SpdySessionKey::IsProxySession::kFalse, socket_tag_1,
2886 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2887 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
2888 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
2889 NetLogWithSource()));
2890 EXPECT_EQ(
2891 dns_aliases,
2892 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key1));
2893
2894 // Clear host resolver rules to ensure that cached values for DNS aliases
2895 // are used.
2896 helper.session_deps()->host_resolver->rules()->ClearRules();
2897
2898 HttpRequestInfo request2;
2899 request2.socket_tag = socket_tag_2;
2900 request2.method = "GET";
2901 request2.url = url;
2902 request2.load_flags = 0;
2903 request2.traffic_annotation =
2904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2905 SpdySessionKey key2(HostPortPair(url.host(), 443), ProxyChain::Direct(),
2906 PRIVACY_MODE_DISABLED,
2907 SpdySessionKey::IsProxySession::kFalse, socket_tag_2,
2908 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2909 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2910 helper.session());
2911 TestCompletionCallback callback2;
2912 EXPECT_THAT(
2913 trans2->Start(&request2, callback2.callback(), NetLogWithSource()),
2914 IsError(ERR_IO_PENDING));
2915
2916 // Wait for the second request to get headers. It should have reused the
2917 // first session but changed the tag.
2918 EXPECT_THAT(callback2.WaitForResult(), IsOk());
2919
2920 EXPECT_EQ(1u, helper.GetSpdySessionCount());
2921 EXPECT_FALSE(helper.session()->spdy_session_pool()->FindAvailableSession(
2922 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
2923 NetLogWithSource()));
2924 EXPECT_TRUE(helper.session()
2925 ->spdy_session_pool()
2926 ->GetDnsAliasesForSessionKey(key1)
2927 .empty());
2928 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
2929 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
2930 NetLogWithSource()));
2931 EXPECT_EQ(
2932 dns_aliases,
2933 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key2));
2934
2935 const HttpResponseInfo* response = trans2->GetResponseInfo();
2936 ASSERT_TRUE(response);
2937 ASSERT_TRUE(response->headers);
2938 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2939 EXPECT_TRUE(response->was_fetched_via_spdy);
2940 EXPECT_TRUE(response->was_alpn_negotiated);
2941 std::string response_data;
2942 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
2943 EXPECT_EQ("hello!", response_data);
2944
2945 helper.VerifyDataConsumed();
2946 }
2947
TEST_P(SpdyNetworkTransactionTest,SocketTagChangeFromIPAliasedSessionWithDnsAliases)2948 TEST_P(SpdyNetworkTransactionTest,
2949 SocketTagChangeFromIPAliasedSessionWithDnsAliases) {
2950 SocketTag socket_tag_1(SocketTag::UNSET_UID, 1);
2951 SocketTag socket_tag_2(SocketTag::UNSET_UID, 2);
2952 request_.socket_tag = socket_tag_1;
2953
2954 std::unique_ptr<SpdySessionDependencies> session_deps =
2955 std::make_unique<SpdySessionDependencies>();
2956 std::unique_ptr<MockCachingHostResolver> host_resolver =
2957 std::make_unique<MockCachingHostResolver>(2 /* cache_invalidation_num */);
2958 session_deps->host_resolver = std::move(host_resolver);
2959
2960 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
2961 std::move(session_deps));
2962 GURL url1 = request_.url;
2963 std::set<std::string> dns_aliases1({"alias1", "alias2", "alias3"});
2964 GURL url2("https://example.test/");
2965 std::set<std::string> dns_aliases2({"example.net", "example.com"});
2966
2967 helper.session_deps()->host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
2968 url1.host(), "127.0.0.1", dns_aliases1);
2969 helper.session_deps()->host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
2970 url2.host(), "127.0.0.1", dns_aliases2);
2971
2972 spdy::SpdySerializedFrame req1(
2973 spdy_util_.ConstructSpdyGet(url1.spec().c_str(), 1, DEFAULT_PRIORITY));
2974 spdy_util_.UpdateWithStreamDestruction(1);
2975 spdy::SpdySerializedFrame req2(
2976 spdy_util_.ConstructSpdyGet(url2.spec().c_str(), 3, DEFAULT_PRIORITY));
2977 spdy_util_.UpdateWithStreamDestruction(3);
2978 spdy::SpdySerializedFrame req3(
2979 spdy_util_.ConstructSpdyGet(url2.spec().c_str(), 5, DEFAULT_PRIORITY));
2980 spdy_util_.UpdateWithStreamDestruction(5);
2981 spdy::SpdySerializedFrame req4(
2982 spdy_util_.ConstructSpdyGet(url1.spec().c_str(), 7, DEFAULT_PRIORITY));
2983 MockWrite writes[] = {
2984 CreateMockWrite(req1, 0),
2985 CreateMockWrite(req2, 3),
2986 CreateMockWrite(req3, 6),
2987 CreateMockWrite(req4, 9),
2988 };
2989
2990 spdy::SpdySerializedFrame resp1(
2991 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2992 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2993 spdy::SpdySerializedFrame resp2(
2994 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2995 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
2996 spdy::SpdySerializedFrame resp3(
2997 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
2998 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
2999 spdy::SpdySerializedFrame resp4(
3000 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7));
3001 spdy::SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(7, true));
3002 MockRead reads[] = {CreateMockRead(resp1, 1),
3003 CreateMockRead(body1, 2),
3004 CreateMockRead(resp2, 4),
3005 CreateMockRead(body2, 5),
3006 CreateMockRead(resp3, 7),
3007 CreateMockRead(body3, 8),
3008 CreateMockRead(resp4, 10),
3009 CreateMockRead(body4, 11),
3010 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 12)};
3011
3012 SequencedSocketData data(MockConnect(ASYNC, OK), reads, writes);
3013 helper.AddData(&data);
3014
3015 // Run a transaction to completion to set up a SPDY session. This can't use
3016 // RunToCompletion(), since it can't call VerifyDataConsumed() yet.
3017 helper.RunPreTestSetup();
3018 helper.RunDefaultTest();
3019 TransactionHelperResult out = helper.output();
3020 EXPECT_THAT(out.rv, IsOk());
3021 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3022 EXPECT_EQ("hello!", out.response_data);
3023
3024 // A new SPDY session should have been created.
3025 EXPECT_EQ(1u, helper.GetSpdySessionCount());
3026 SpdySessionKey key1(HostPortPair(url1.host(), 443), ProxyChain::Direct(),
3027 PRIVACY_MODE_DISABLED,
3028 SpdySessionKey::IsProxySession::kFalse, socket_tag_1,
3029 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3030 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
3031 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
3032 NetLogWithSource()));
3033 EXPECT_EQ(
3034 dns_aliases1,
3035 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key1));
3036
3037 HttpRequestInfo request2;
3038 request2.socket_tag = socket_tag_1;
3039 request2.method = "GET";
3040 request2.url = url2;
3041 request2.load_flags = 0;
3042 request2.traffic_annotation =
3043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3044 SpdySessionKey key2(HostPortPair(url2.host(), 443), ProxyChain::Direct(),
3045 PRIVACY_MODE_DISABLED,
3046 SpdySessionKey::IsProxySession::kFalse, socket_tag_1,
3047 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3048 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
3049 helper.session());
3050 TestCompletionCallback callback2;
3051 EXPECT_THAT(
3052 trans2->Start(&request2, callback2.callback(), NetLogWithSource()),
3053 IsError(ERR_IO_PENDING));
3054
3055 // Wait for the second request to get headers. It should have reused the
3056 // first session.
3057 EXPECT_THAT(callback2.WaitForResult(), IsOk());
3058
3059 EXPECT_EQ(1u, helper.GetSpdySessionCount());
3060 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
3061 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
3062 NetLogWithSource()));
3063 EXPECT_EQ(
3064 dns_aliases2,
3065 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key2));
3066
3067 const HttpResponseInfo* response = trans2->GetResponseInfo();
3068 ASSERT_TRUE(response);
3069 ASSERT_TRUE(response->headers);
3070 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3071 EXPECT_TRUE(response->was_fetched_via_spdy);
3072 EXPECT_TRUE(response->was_alpn_negotiated);
3073 std::string response_data;
3074 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
3075 EXPECT_EQ("hello!", response_data);
3076
3077 // Clear host resolver rules to ensure that cached values for DNS aliases
3078 // are used.
3079 helper.session_deps()->host_resolver->rules()->ClearRules();
3080 trans2.reset();
3081
3082 HttpRequestInfo request3;
3083 request3.socket_tag = socket_tag_2;
3084 request3.method = "GET";
3085 request3.url = url2;
3086 request3.load_flags = 0;
3087 request3.traffic_annotation =
3088 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3089 SpdySessionKey key3(HostPortPair(url2.host(), 443), ProxyChain::Direct(),
3090 PRIVACY_MODE_DISABLED,
3091 SpdySessionKey::IsProxySession::kFalse, socket_tag_2,
3092 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3093 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
3094 helper.session());
3095 TestCompletionCallback callback3;
3096 EXPECT_THAT(
3097 trans3->Start(&request3, callback3.callback(), NetLogWithSource()),
3098 IsError(ERR_IO_PENDING));
3099
3100 // Wait for the third request to get headers. It should have reused the
3101 // first session but changed the socket tag.
3102 EXPECT_THAT(callback3.WaitForResult(), IsOk());
3103
3104 EXPECT_EQ(1u, helper.GetSpdySessionCount());
3105 EXPECT_FALSE(helper.session()->spdy_session_pool()->FindAvailableSession(
3106 key2, true /* enable_ip_based_pooling */, false /* is_websocket */,
3107 NetLogWithSource()));
3108 EXPECT_TRUE(helper.session()
3109 ->spdy_session_pool()
3110 ->GetDnsAliasesForSessionKey(key2)
3111 .empty());
3112 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
3113 key3, true /* enable_ip_based_pooling */, false /* is_websocket */,
3114 NetLogWithSource()));
3115 EXPECT_EQ(
3116 dns_aliases2,
3117 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key3));
3118
3119 response = trans3->GetResponseInfo();
3120 ASSERT_TRUE(response);
3121 ASSERT_TRUE(response->headers);
3122 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3123 EXPECT_TRUE(response->was_fetched_via_spdy);
3124 EXPECT_TRUE(response->was_alpn_negotiated);
3125 ASSERT_THAT(ReadTransaction(trans3.get(), &response_data), IsOk());
3126 EXPECT_EQ("hello!", response_data);
3127
3128 trans3.reset();
3129
3130 HttpRequestInfo request4;
3131 request4.socket_tag = socket_tag_2;
3132 request4.method = "GET";
3133 request4.url = url1;
3134 request4.load_flags = 0;
3135 request4.traffic_annotation =
3136 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3137 SpdySessionKey key4(HostPortPair(url1.host(), 443), ProxyChain::Direct(),
3138 PRIVACY_MODE_DISABLED,
3139 SpdySessionKey::IsProxySession::kFalse, socket_tag_2,
3140 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3141 auto trans4 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
3142 helper.session());
3143 TestCompletionCallback callback4;
3144 EXPECT_THAT(
3145 trans4->Start(&request4, callback4.callback(), NetLogWithSource()),
3146 IsError(ERR_IO_PENDING));
3147
3148 // Wait for the third request to get headers. It should have reused the
3149 // first session but changed the socket tag.
3150 EXPECT_THAT(callback4.WaitForResult(), IsOk());
3151
3152 EXPECT_EQ(1u, helper.GetSpdySessionCount());
3153 EXPECT_FALSE(helper.session()->spdy_session_pool()->FindAvailableSession(
3154 key1, true /* enable_ip_based_pooling */, false /* is_websocket */,
3155 NetLogWithSource()));
3156 EXPECT_TRUE(helper.session()
3157 ->spdy_session_pool()
3158 ->GetDnsAliasesForSessionKey(key1)
3159 .empty());
3160 EXPECT_TRUE(helper.session()->spdy_session_pool()->FindAvailableSession(
3161 key4, true /* enable_ip_based_pooling */, false /* is_websocket */,
3162 NetLogWithSource()));
3163 EXPECT_EQ(
3164 dns_aliases1,
3165 helper.session()->spdy_session_pool()->GetDnsAliasesForSessionKey(key4));
3166
3167 response = trans4->GetResponseInfo();
3168 ASSERT_TRUE(response);
3169 ASSERT_TRUE(response->headers);
3170 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3171 EXPECT_TRUE(response->was_fetched_via_spdy);
3172 EXPECT_TRUE(response->was_alpn_negotiated);
3173 ASSERT_THAT(ReadTransaction(trans4.get(), &response_data), IsOk());
3174 EXPECT_EQ("hello!", response_data);
3175
3176 helper.VerifyDataConsumed();
3177 }
3178
3179 #endif // BUILDFLAG(IS_ANDROID)
3180
3181 // Verify that various response headers parse correctly through the HTTP layer.
TEST_P(SpdyNetworkTransactionTest,ResponseHeaders)3182 TEST_P(SpdyNetworkTransactionTest, ResponseHeaders) {
3183 struct ResponseHeadersTests {
3184 int extra_header_count;
3185 const char* extra_headers[4];
3186 size_t expected_header_count;
3187 base::StringPiece expected_headers[8];
3188 } test_cases[] = {
3189 // No extra headers.
3190 {0, {}, 1, {"hello", "bye"}},
3191 // Comma-separated header value.
3192 {1,
3193 {"cookie", "val1, val2"},
3194 2,
3195 {"hello", "bye", "cookie", "val1, val2"}},
3196 // Multiple headers are preserved: they are joined with \0 separator in
3197 // spdy::Http2HeaderBlock.AppendValueOrAddHeader(), then split up in
3198 // HpackEncoder, then joined with \0 separator when
3199 // spdy::HpackDecoderAdapter::ListenerAdapter::OnHeader() calls
3200 // spdy::Http2HeaderBlock.AppendValueOrAddHeader(), then split up again in
3201 // HttpResponseHeaders.
3202 {2,
3203 {"content-encoding", "val1", "content-encoding", "val2"},
3204 3,
3205 {"hello", "bye", "content-encoding", "val1", "content-encoding",
3206 "val2"}},
3207 // Cookie header is not split up by HttpResponseHeaders.
3208 {2,
3209 {"cookie", "val1", "cookie", "val2"},
3210 2,
3211 {"hello", "bye", "cookie", "val1; val2"}}};
3212
3213 for (size_t i = 0; i < std::size(test_cases); ++i) {
3214 SCOPED_TRACE(i);
3215 SpdyTestUtil spdy_test_util(/*use_priority_header=*/true);
3216 spdy::SpdySerializedFrame req(
3217 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3218 MockWrite writes[] = {CreateMockWrite(req, 0)};
3219
3220 spdy::SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply(
3221 test_cases[i].extra_headers, test_cases[i].extra_header_count, 1));
3222 spdy::SpdySerializedFrame body(
3223 spdy_test_util.ConstructSpdyDataFrame(1, true));
3224 MockRead reads[] = {
3225 CreateMockRead(resp, 1), CreateMockRead(body, 2),
3226 MockRead(ASYNC, 0, 3) // EOF
3227 };
3228
3229 SequencedSocketData data(reads, writes);
3230 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
3231 nullptr);
3232 helper.RunToCompletion(&data);
3233 TransactionHelperResult out = helper.output();
3234
3235 EXPECT_THAT(out.rv, IsOk());
3236 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3237 EXPECT_EQ("hello!", out.response_data);
3238
3239 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3240 ASSERT_TRUE(headers);
3241 EXPECT_EQ("HTTP/1.1 200", headers->GetStatusLine());
3242 size_t iter = 0;
3243 std::string name, value;
3244 size_t expected_header_index = 0;
3245 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3246 ASSERT_LT(expected_header_index, test_cases[i].expected_header_count);
3247 EXPECT_EQ(name,
3248 test_cases[i].expected_headers[2 * expected_header_index]);
3249 EXPECT_EQ(value,
3250 test_cases[i].expected_headers[2 * expected_header_index + 1]);
3251 ++expected_header_index;
3252 }
3253 EXPECT_EQ(expected_header_index, test_cases[i].expected_header_count);
3254 }
3255 }
3256
3257 // Verify that we don't crash on invalid response headers.
TEST_P(SpdyNetworkTransactionTest,InvalidResponseHeaders)3258 TEST_P(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
3259 struct InvalidResponseHeadersTests {
3260 int num_headers;
3261 const char* headers[10];
3262 } test_cases[] = {// Response headers missing status header
3263 {2, {"cookie", "val1", "cookie", "val2", nullptr}},
3264 // Response headers with no headers
3265 {0, {nullptr}}};
3266
3267 for (size_t i = 0; i < std::size(test_cases); ++i) {
3268 SCOPED_TRACE(i);
3269 SpdyTestUtil spdy_test_util(/*use_priority_header=*/true);
3270
3271 spdy::SpdySerializedFrame req(
3272 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3273 spdy::SpdySerializedFrame rst(spdy_test_util.ConstructSpdyRstStream(
3274 1, spdy::ERROR_CODE_PROTOCOL_ERROR));
3275 MockWrite writes[] = {
3276 CreateMockWrite(req, 0),
3277 CreateMockWrite(rst, 2),
3278 };
3279
3280 // Construct the reply.
3281 spdy::Http2HeaderBlock reply_headers;
3282 AppendToHeaderBlock(test_cases[i].headers, test_cases[i].num_headers,
3283 &reply_headers);
3284 spdy::SpdySerializedFrame resp(
3285 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
3286 MockRead reads[] = {
3287 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3) // EOF
3288 };
3289
3290 SequencedSocketData data(reads, writes);
3291 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
3292 nullptr);
3293 helper.RunToCompletion(&data);
3294 TransactionHelperResult out = helper.output();
3295 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
3296 }
3297 }
3298
TEST_P(SpdyNetworkTransactionTest,CorruptFrameSessionError)3299 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3300 spdy::SpdySerializedFrame req(
3301 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3302 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3303 0, spdy::ERROR_CODE_COMPRESSION_ERROR,
3304 "Framer error: 24 (HPACK_TRUNCATED_BLOCK)."));
3305 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
3306
3307 // This is the length field that's too short.
3308 spdy::SpdySerializedFrame reply_wrong_length(
3309 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3310 size_t right_size = reply_wrong_length.size() - spdy::kFrameHeaderSize;
3311 size_t wrong_size = right_size - 4;
3312 spdy::test::SetFrameLength(&reply_wrong_length, wrong_size);
3313
3314 MockRead reads[] = {
3315 MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
3316 1),
3317 };
3318
3319 SequencedSocketData data(reads, writes);
3320 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3321 helper.RunToCompletion(&data);
3322 TransactionHelperResult out = helper.output();
3323 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_COMPRESSION_ERROR));
3324 }
3325
TEST_P(SpdyNetworkTransactionTest,GoAwayOnDecompressionFailure)3326 TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3327 spdy::SpdySerializedFrame req(
3328 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3329 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3330 0, spdy::ERROR_CODE_COMPRESSION_ERROR,
3331 "Framer error: 24 (HPACK_TRUNCATED_BLOCK)."));
3332 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
3333
3334 // Read HEADERS with corrupted payload.
3335 spdy::SpdySerializedFrame resp(
3336 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3337 memset(resp.data() + 12, 0xcf, resp.size() - 12);
3338 MockRead reads[] = {CreateMockRead(resp, 1)};
3339
3340 SequencedSocketData data(reads, writes);
3341 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3342 helper.RunToCompletion(&data);
3343 TransactionHelperResult out = helper.output();
3344 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_COMPRESSION_ERROR));
3345 }
3346
TEST_P(SpdyNetworkTransactionTest,GoAwayOnFrameSizeError)3347 TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3348 spdy::SpdySerializedFrame req(
3349 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3350 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3351 0, spdy::ERROR_CODE_FRAME_SIZE_ERROR,
3352 "Framer error: 9 (INVALID_CONTROL_FRAME_SIZE)."));
3353 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
3354
3355 // Read WINDOW_UPDATE with incorrectly-sized payload.
3356 spdy::SpdySerializedFrame bad_window_update(
3357 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3358 spdy::test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1);
3359 MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
3360
3361 SequencedSocketData data(reads, writes);
3362 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3363 helper.RunToCompletion(&data);
3364 TransactionHelperResult out = helper.output();
3365 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_FRAME_SIZE_ERROR));
3366 }
3367
3368 // Test that we shutdown correctly on write errors.
TEST_P(SpdyNetworkTransactionTest,WriteError)3369 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3370 spdy::SpdySerializedFrame req(
3371 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3372 MockWrite writes[] = {
3373 // We'll write 10 bytes successfully
3374 MockWrite(ASYNC, req.data(), 10, 1),
3375 // Followed by ERROR!
3376 MockWrite(ASYNC, ERR_FAILED, 2),
3377 // Session drains and attempts to write a GOAWAY: Another ERROR!
3378 MockWrite(ASYNC, ERR_FAILED, 3),
3379 };
3380
3381 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
3382
3383 SequencedSocketData data(reads, writes);
3384
3385 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3386 helper.RunPreTestSetup();
3387 helper.AddData(&data);
3388 EXPECT_TRUE(helper.StartDefaultTest());
3389 helper.FinishDefaultTest();
3390 EXPECT_TRUE(data.AllWriteDataConsumed());
3391 EXPECT_TRUE(data.AllReadDataConsumed());
3392 TransactionHelperResult out = helper.output();
3393 EXPECT_THAT(out.rv, IsError(ERR_FAILED));
3394 }
3395
3396 // Test that partial writes work.
TEST_P(SpdyNetworkTransactionTest,PartialWrite)3397 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3398 // Chop the HEADERS frame into 5 chunks.
3399 spdy::SpdySerializedFrame req(
3400 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3401 const size_t kChunks = 5u;
3402 std::unique_ptr<MockWrite[]> writes = ChopWriteFrame(req, kChunks);
3403 for (size_t i = 0; i < kChunks; ++i) {
3404 writes[i].sequence_number = i;
3405 }
3406
3407 spdy::SpdySerializedFrame resp(
3408 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3409 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
3410 MockRead reads[] = {
3411 CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
3412 MockRead(ASYNC, 0, kChunks + 2) // EOF
3413 };
3414
3415 SequencedSocketData data(reads, base::make_span(writes.get(), kChunks));
3416 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3417 helper.RunToCompletion(&data);
3418 TransactionHelperResult out = helper.output();
3419 EXPECT_THAT(out.rv, IsOk());
3420 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3421 EXPECT_EQ("hello!", out.response_data);
3422 }
3423
3424 // Test that the NetLog contains good data for a simple GET request.
TEST_P(SpdyNetworkTransactionTest,NetLog)3425 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3426 static const char* const kExtraHeaders[] = {
3427 "user-agent",
3428 "Chrome",
3429 };
3430 spdy::SpdySerializedFrame req(
3431 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST));
3432 MockWrite writes[] = {CreateMockWrite(req, 0)};
3433
3434 spdy::SpdySerializedFrame resp(
3435 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3436 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
3437 MockRead reads[] = {
3438 CreateMockRead(resp, 1), CreateMockRead(body, 2),
3439 MockRead(ASYNC, 0, 3) // EOF
3440 };
3441
3442 RecordingNetLogObserver net_log_observer;
3443
3444 SequencedSocketData data(reads, writes);
3445 request_.extra_headers.SetHeader("User-Agent", "Chrome");
3446 NormalSpdyTransactionHelper helper(
3447 request_, DEFAULT_PRIORITY,
3448 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
3449 helper.RunToCompletion(&data);
3450 TransactionHelperResult out = helper.output();
3451 EXPECT_THAT(out.rv, IsOk());
3452 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3453 EXPECT_EQ("hello!", out.response_data);
3454
3455 // Check that the NetLog was filled reasonably.
3456 // This test is intentionally non-specific about the exact ordering of the
3457 // log; instead we just check to make sure that certain events exist, and that
3458 // they are in the right order.
3459 auto entries = net_log_observer.GetEntries();
3460
3461 EXPECT_LT(0u, entries.size());
3462 int pos = 0;
3463 pos = ExpectLogContainsSomewhere(
3464 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3465 NetLogEventPhase::BEGIN);
3466 pos = ExpectLogContainsSomewhere(
3467 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3468 NetLogEventPhase::END);
3469 pos = ExpectLogContainsSomewhere(
3470 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3471 NetLogEventPhase::BEGIN);
3472 pos = ExpectLogContainsSomewhere(
3473 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3474 NetLogEventPhase::END);
3475 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3476 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3477 NetLogEventPhase::BEGIN);
3478 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3479 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3480 NetLogEventPhase::END);
3481
3482 // Check that we logged all the headers correctly
3483 pos = ExpectLogContainsSomewhere(entries, 0,
3484 NetLogEventType::HTTP2_SESSION_SEND_HEADERS,
3485 NetLogEventPhase::NONE);
3486
3487 ASSERT_TRUE(entries[pos].HasParams());
3488 auto* header_list = entries[pos].params.FindList("headers");
3489 ASSERT_TRUE(header_list);
3490 if (base::FeatureList::IsEnabled(net::features::kPriorityHeader)) {
3491 ASSERT_EQ(6u, header_list->size());
3492 } else {
3493 ASSERT_EQ(5u, header_list->size());
3494 }
3495
3496 ASSERT_TRUE((*header_list)[0].is_string());
3497 EXPECT_EQ(":method: GET", (*header_list)[0].GetString());
3498
3499 ASSERT_TRUE((*header_list)[1].is_string());
3500 EXPECT_EQ(":authority: www.example.org", (*header_list)[1].GetString());
3501
3502 ASSERT_TRUE((*header_list)[2].is_string());
3503 EXPECT_EQ(":scheme: https", (*header_list)[2].GetString());
3504
3505 ASSERT_TRUE((*header_list)[3].is_string());
3506 EXPECT_EQ(":path: /", (*header_list)[3].GetString());
3507
3508 ASSERT_TRUE((*header_list)[4].is_string());
3509 EXPECT_EQ("user-agent: Chrome", (*header_list)[4].GetString());
3510
3511 // Incoming HEADERS frame is logged as HTTP2_SESSION_RECV_HEADERS.
3512 pos = ExpectLogContainsSomewhere(entries, 0,
3513 NetLogEventType::HTTP2_SESSION_RECV_HEADERS,
3514 NetLogEventPhase::NONE);
3515 ASSERT_TRUE(entries[pos].HasParams());
3516 // END_STREAM is not set on the HEADERS frame, so `fin` is false.
3517 absl::optional<bool> fin = entries[pos].params.FindBool("fin");
3518 ASSERT_TRUE(fin.has_value());
3519 EXPECT_FALSE(*fin);
3520
3521 // Incoming DATA frame is logged as HTTP2_SESSION_RECV_DATA.
3522 pos = ExpectLogContainsSomewhere(entries, 0,
3523 NetLogEventType::HTTP2_SESSION_RECV_DATA,
3524 NetLogEventPhase::NONE);
3525 ASSERT_TRUE(entries[pos].HasParams());
3526 absl::optional<int> size = entries[pos].params.FindInt("size");
3527 ASSERT_TRUE(size.has_value());
3528 EXPECT_EQ(static_cast<int>(strlen("hello!")), *size);
3529 // END_STREAM is set on the DATA frame, so `fin` is true.
3530 fin = entries[pos].params.FindBool("fin");
3531 ASSERT_TRUE(fin.has_value());
3532 EXPECT_TRUE(*fin);
3533 }
3534
TEST_P(SpdyNetworkTransactionTest,NetLogForResponseWithNoBody)3535 TEST_P(SpdyNetworkTransactionTest, NetLogForResponseWithNoBody) {
3536 spdy::SpdySerializedFrame req(
3537 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3538 MockWrite writes[] = {CreateMockWrite(req, 0)};
3539
3540 spdy::Http2HeaderBlock response_headers;
3541 response_headers[spdy::kHttp2StatusHeader] = "200";
3542 response_headers["hello"] = "bye";
3543 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
3544 1, std::move(response_headers), /* fin = */ true));
3545 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
3546
3547 RecordingNetLogObserver net_log_observer;
3548
3549 SequencedSocketData data(reads, writes);
3550 NormalSpdyTransactionHelper helper(
3551 request_, DEFAULT_PRIORITY,
3552 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
3553 helper.RunToCompletion(&data);
3554 TransactionHelperResult out = helper.output();
3555 EXPECT_THAT(out.rv, IsOk());
3556 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3557 EXPECT_EQ("", out.response_data);
3558
3559 // Incoming HEADERS frame is logged as HTTP2_SESSION_RECV_HEADERS.
3560 auto entries = net_log_observer.GetEntries();
3561 int pos = ExpectLogContainsSomewhere(
3562 entries, 0, NetLogEventType::HTTP2_SESSION_RECV_HEADERS,
3563 NetLogEventPhase::NONE);
3564 ASSERT_TRUE(entries[pos].HasParams());
3565 // END_STREAM is set on the HEADERS frame, so `fin` is true.
3566 absl::optional<bool> fin = entries[pos].params.FindBool("fin");
3567 ASSERT_TRUE(fin.has_value());
3568 EXPECT_TRUE(*fin);
3569
3570 // No DATA frame is received.
3571 EXPECT_FALSE(LogContainsEntryWithTypeAfter(
3572 entries, 0, NetLogEventType::HTTP2_SESSION_RECV_DATA));
3573 }
3574
3575 // Since we buffer the IO from the stream to the renderer, this test verifies
3576 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3577 // on the network, but issued a Read for only 5 of those bytes) that the data
3578 // flow still works correctly.
TEST_P(SpdyNetworkTransactionTest,BufferFull)3579 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3580 spdy::SpdySerializedFrame req(
3581 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3582 MockWrite writes[] = {CreateMockWrite(req, 0)};
3583
3584 // 2 data frames in a single read.
3585 spdy::SpdySerializedFrame data_frame_1(
3586 spdy_util_.ConstructSpdyDataFrame(1, "goodby", /*fin=*/false));
3587 spdy::SpdySerializedFrame data_frame_2(
3588 spdy_util_.ConstructSpdyDataFrame(1, "e worl", /*fin=*/false));
3589 spdy::SpdySerializedFrame combined_data_frames =
3590 CombineFrames({&data_frame_1, &data_frame_2});
3591
3592 spdy::SpdySerializedFrame last_frame(
3593 spdy_util_.ConstructSpdyDataFrame(1, "d", /*fin=*/true));
3594
3595 spdy::SpdySerializedFrame resp(
3596 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3597 MockRead reads[] = {
3598 CreateMockRead(resp, 1),
3599 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3600 CreateMockRead(combined_data_frames, 3),
3601 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
3602 CreateMockRead(last_frame, 5),
3603 MockRead(ASYNC, 0, 6) // EOF
3604 };
3605
3606 SequencedSocketData data(reads, writes);
3607
3608 TestCompletionCallback callback;
3609
3610 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3611 helper.RunPreTestSetup();
3612 helper.AddData(&data);
3613 HttpNetworkTransaction* trans = helper.trans();
3614 int rv = trans->Start(&request_, callback.callback(), log_);
3615 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3616
3617 TransactionHelperResult out = helper.output();
3618 out.rv = callback.WaitForResult();
3619 EXPECT_EQ(out.rv, OK);
3620
3621 const HttpResponseInfo* response = trans->GetResponseInfo();
3622 EXPECT_TRUE(response->headers);
3623 EXPECT_TRUE(response->was_fetched_via_spdy);
3624 out.status_line = response->headers->GetStatusLine();
3625 out.response_info = *response; // Make a copy so we can verify.
3626
3627 // Read Data
3628 TestCompletionCallback read_callback;
3629
3630 std::string content;
3631 do {
3632 // Read small chunks at a time.
3633 const int kSmallReadSize = 3;
3634 auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
3635 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3636 if (rv == ERR_IO_PENDING) {
3637 data.Resume();
3638 rv = read_callback.WaitForResult();
3639 }
3640 if (rv > 0) {
3641 content.append(buf->data(), rv);
3642 } else if (rv < 0) {
3643 NOTREACHED();
3644 }
3645 } while (rv > 0);
3646
3647 out.response_data.swap(content);
3648
3649 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3650 // MockClientSocketFactory) are still alive.
3651 base::RunLoop().RunUntilIdle();
3652
3653 // Verify that we consumed all test data.
3654 helper.VerifyDataConsumed();
3655
3656 EXPECT_THAT(out.rv, IsOk());
3657 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3658 EXPECT_EQ("goodbye world", out.response_data);
3659 }
3660
3661 // Verify that basic buffering works; when multiple data frames arrive
3662 // at the same time, ensure that we don't notify a read completion for
3663 // each data frame individually.
TEST_P(SpdyNetworkTransactionTest,Buffering)3664 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3665 spdy::SpdySerializedFrame req(
3666 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3667 MockWrite writes[] = {CreateMockWrite(req, 0)};
3668
3669 // 4 data frames in a single read.
3670 spdy::SpdySerializedFrame data_frame(
3671 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
3672 spdy::SpdySerializedFrame data_frame_fin(
3673 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/true));
3674 spdy::SpdySerializedFrame combined_data_frames =
3675 CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame_fin});
3676
3677 spdy::SpdySerializedFrame resp(
3678 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3679 MockRead reads[] = {
3680 CreateMockRead(resp, 1),
3681 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3682 CreateMockRead(combined_data_frames, 3), MockRead(ASYNC, 0, 4) // EOF
3683 };
3684
3685 SequencedSocketData data(reads, writes);
3686
3687 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3688 helper.RunPreTestSetup();
3689 helper.AddData(&data);
3690 HttpNetworkTransaction* trans = helper.trans();
3691
3692 TestCompletionCallback callback;
3693 int rv = trans->Start(&request_, callback.callback(), log_);
3694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3695
3696 TransactionHelperResult out = helper.output();
3697 out.rv = callback.WaitForResult();
3698 EXPECT_EQ(out.rv, OK);
3699
3700 const HttpResponseInfo* response = trans->GetResponseInfo();
3701 EXPECT_TRUE(response->headers);
3702 EXPECT_TRUE(response->was_fetched_via_spdy);
3703 out.status_line = response->headers->GetStatusLine();
3704 out.response_info = *response; // Make a copy so we can verify.
3705
3706 // Read Data
3707 TestCompletionCallback read_callback;
3708
3709 std::string content;
3710 int reads_completed = 0;
3711 do {
3712 // Read small chunks at a time.
3713 const int kSmallReadSize = 14;
3714 auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
3715 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3716 if (rv == ERR_IO_PENDING) {
3717 data.Resume();
3718 rv = read_callback.WaitForResult();
3719 }
3720 if (rv > 0) {
3721 EXPECT_EQ(kSmallReadSize, rv);
3722 content.append(buf->data(), rv);
3723 } else if (rv < 0) {
3724 FAIL() << "Unexpected read error: " << rv;
3725 }
3726 reads_completed++;
3727 } while (rv > 0);
3728
3729 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3730
3731 out.response_data.swap(content);
3732
3733 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3734 // MockClientSocketFactory) are still alive.
3735 base::RunLoop().RunUntilIdle();
3736
3737 // Verify that we consumed all test data.
3738 helper.VerifyDataConsumed();
3739
3740 EXPECT_THAT(out.rv, IsOk());
3741 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3742 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3743 }
3744
3745 // Verify the case where we buffer data but read it after it has been buffered.
TEST_P(SpdyNetworkTransactionTest,BufferedAll)3746 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3747 spdy::SpdySerializedFrame req(
3748 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3749 MockWrite writes[] = {CreateMockWrite(req, 0)};
3750
3751 // 5 data frames in a single read.
3752 spdy::SpdySerializedFrame reply(
3753 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3754 spdy::SpdySerializedFrame data_frame(
3755 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
3756 spdy::SpdySerializedFrame data_frame_fin(
3757 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/true));
3758 spdy::SpdySerializedFrame combined_frames = CombineFrames(
3759 {&reply, &data_frame, &data_frame, &data_frame, &data_frame_fin});
3760
3761 MockRead reads[] = {
3762 CreateMockRead(combined_frames, 1), MockRead(ASYNC, 0, 2) // EOF
3763 };
3764
3765 SequencedSocketData data(reads, writes);
3766
3767 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3768 helper.RunPreTestSetup();
3769 helper.AddData(&data);
3770 HttpNetworkTransaction* trans = helper.trans();
3771
3772 TestCompletionCallback callback;
3773 int rv = trans->Start(&request_, callback.callback(), log_);
3774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3775
3776 TransactionHelperResult out = helper.output();
3777 out.rv = callback.WaitForResult();
3778 EXPECT_EQ(out.rv, OK);
3779
3780 const HttpResponseInfo* response = trans->GetResponseInfo();
3781 EXPECT_TRUE(response->headers);
3782 EXPECT_TRUE(response->was_fetched_via_spdy);
3783 out.status_line = response->headers->GetStatusLine();
3784 out.response_info = *response; // Make a copy so we can verify.
3785
3786 // Read Data
3787 TestCompletionCallback read_callback;
3788
3789 std::string content;
3790 int reads_completed = 0;
3791 do {
3792 // Read small chunks at a time.
3793 const int kSmallReadSize = 14;
3794 auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
3795 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3796 if (rv > 0) {
3797 EXPECT_EQ(kSmallReadSize, rv);
3798 content.append(buf->data(), rv);
3799 } else if (rv < 0) {
3800 FAIL() << "Unexpected read error: " << rv;
3801 }
3802 reads_completed++;
3803 } while (rv > 0);
3804
3805 EXPECT_EQ(3, reads_completed);
3806
3807 out.response_data.swap(content);
3808
3809 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3810 // MockClientSocketFactory) are still alive.
3811 base::RunLoop().RunUntilIdle();
3812
3813 // Verify that we consumed all test data.
3814 helper.VerifyDataConsumed();
3815
3816 EXPECT_THAT(out.rv, IsOk());
3817 EXPECT_EQ("HTTP/1.1 200", out.status_line);
3818 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3819 }
3820
3821 // Verify the case where we buffer data and close the connection.
TEST_P(SpdyNetworkTransactionTest,BufferedClosed)3822 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
3823 spdy::SpdySerializedFrame req(
3824 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3825 MockWrite writes[] = {CreateMockWrite(req, 0)};
3826
3827 // All data frames in a single read.
3828 // NOTE: We don't FIN the stream.
3829 spdy::SpdySerializedFrame data_frame(
3830 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
3831 spdy::SpdySerializedFrame combined_data_frames =
3832 CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame});
3833 spdy::SpdySerializedFrame resp(
3834 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3835 MockRead reads[] = {
3836 CreateMockRead(resp, 1),
3837 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3838 CreateMockRead(combined_data_frames, 3), MockRead(ASYNC, 0, 4) // EOF
3839 };
3840
3841 SequencedSocketData data(reads, writes);
3842
3843 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3844 helper.RunPreTestSetup();
3845 helper.AddData(&data);
3846 HttpNetworkTransaction* trans = helper.trans();
3847
3848 TestCompletionCallback callback;
3849
3850 int rv = trans->Start(&request_, callback.callback(), log_);
3851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3852
3853 TransactionHelperResult out = helper.output();
3854 rv = callback.WaitForResult();
3855 EXPECT_EQ(rv, OK);
3856
3857 const HttpResponseInfo* response = trans->GetResponseInfo();
3858 EXPECT_TRUE(response->headers);
3859 EXPECT_TRUE(response->was_fetched_via_spdy);
3860
3861 // Read Data
3862 TestCompletionCallback read_callback;
3863
3864 std::string content;
3865 int reads_completed = 0;
3866 do {
3867 // Allocate a large buffer to allow buffering. If a single read fills the
3868 // buffer, no buffering happens.
3869 const int kLargeReadSize = 1000;
3870 auto buf = base::MakeRefCounted<IOBufferWithSize>(kLargeReadSize);
3871 rv = trans->Read(buf.get(), kLargeReadSize, read_callback.callback());
3872 if (rv == ERR_IO_PENDING) {
3873 data.Resume();
3874 rv = read_callback.WaitForResult();
3875 }
3876
3877 if (rv < 0) {
3878 // This test intentionally closes the connection, and will get an error.
3879 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
3880 break;
3881 }
3882 reads_completed++;
3883 } while (rv > 0);
3884
3885 EXPECT_EQ(0, reads_completed);
3886
3887 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3888 // MockClientSocketFactory) are still alive.
3889 base::RunLoop().RunUntilIdle();
3890
3891 // Verify that we consumed all test data.
3892 helper.VerifyDataConsumed();
3893 }
3894
3895 // Verify the case where we buffer data and cancel the transaction.
TEST_P(SpdyNetworkTransactionTest,BufferedCancelled)3896 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
3897 spdy::SpdySerializedFrame req(
3898 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3899 spdy::SpdySerializedFrame rst(
3900 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
3901 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
3902
3903 // NOTE: We don't FIN the stream.
3904 spdy::SpdySerializedFrame data_frame(
3905 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
3906
3907 spdy::SpdySerializedFrame resp(
3908 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3909 MockRead reads[] = {
3910 CreateMockRead(resp, 1),
3911 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3912 CreateMockRead(data_frame, 3), MockRead(ASYNC, 0, 5) // EOF
3913 };
3914
3915 SequencedSocketData data(reads, writes);
3916
3917 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3918 helper.RunPreTestSetup();
3919 helper.AddData(&data);
3920 HttpNetworkTransaction* trans = helper.trans();
3921 TestCompletionCallback callback;
3922
3923 int rv = trans->Start(&request_, callback.callback(), log_);
3924 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3925
3926 TransactionHelperResult out = helper.output();
3927 out.rv = callback.WaitForResult();
3928 EXPECT_EQ(out.rv, OK);
3929
3930 const HttpResponseInfo* response = trans->GetResponseInfo();
3931 EXPECT_TRUE(response->headers);
3932 EXPECT_TRUE(response->was_fetched_via_spdy);
3933 out.status_line = response->headers->GetStatusLine();
3934 out.response_info = *response; // Make a copy so we can verify.
3935
3936 // Read Data
3937 TestCompletionCallback read_callback;
3938
3939 const int kReadSize = 256;
3940 auto buf = base::MakeRefCounted<IOBufferWithSize>(kReadSize);
3941 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
3942 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
3943
3944 // Complete the read now, which causes buffering to start.
3945 data.Resume();
3946 base::RunLoop().RunUntilIdle();
3947 // Destroy the transaction, causing the stream to get cancelled
3948 // and orphaning the buffered IO task.
3949 helper.ResetTrans();
3950
3951 // Flush the MessageLoop; this will cause the buffered IO task
3952 // to run for the final time.
3953 base::RunLoop().RunUntilIdle();
3954
3955 // Verify that we consumed all test data.
3956 helper.VerifyDataConsumed();
3957 }
3958
3959 // Request should fail upon receiving a GOAWAY frame
3960 // with Last-Stream-ID lower than the stream id corresponding to the request
3961 // and with error code other than NO_ERROR.
TEST_P(SpdyNetworkTransactionTest,FailOnGoAway)3962 TEST_P(SpdyNetworkTransactionTest, FailOnGoAway) {
3963 spdy::SpdySerializedFrame req(
3964 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3965 MockWrite writes[] = {CreateMockWrite(req, 0)};
3966
3967 spdy::SpdySerializedFrame go_away(
3968 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_INTERNAL_ERROR, ""));
3969 MockRead reads[] = {
3970 CreateMockRead(go_away, 1),
3971 };
3972
3973 SequencedSocketData data(reads, writes);
3974 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3975 helper.RunToCompletion(&data);
3976 TransactionHelperResult out = helper.output();
3977 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
3978 }
3979
3980 // Request should be retried on a new connection upon receiving a GOAWAY frame
3981 // with Last-Stream-ID lower than the stream id corresponding to the request
3982 // and with error code NO_ERROR.
TEST_P(SpdyNetworkTransactionTest,RetryOnGoAway)3983 TEST_P(SpdyNetworkTransactionTest, RetryOnGoAway) {
3984 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3985
3986 // First connection.
3987 spdy::SpdySerializedFrame req(
3988 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3989 MockWrite writes1[] = {CreateMockWrite(req, 0)};
3990 spdy::SpdySerializedFrame go_away(
3991 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_NO_ERROR, ""));
3992 MockRead reads1[] = {CreateMockRead(go_away, 1)};
3993 SequencedSocketData data1(reads1, writes1);
3994 helper.AddData(&data1);
3995
3996 // Second connection.
3997 MockWrite writes2[] = {CreateMockWrite(req, 0)};
3998 spdy::SpdySerializedFrame resp(
3999 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4000 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
4001 MockRead reads2[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
4002 MockRead(ASYNC, 0, 3)};
4003 SequencedSocketData data2(reads2, writes2);
4004 helper.AddData(&data2);
4005
4006 helper.RunPreTestSetup();
4007 helper.RunDefaultTest();
4008
4009 TransactionHelperResult out = helper.output();
4010 EXPECT_THAT(out.rv, IsOk());
4011
4012 helper.VerifyDataConsumed();
4013 }
4014
4015 // A server can gracefully shut down by sending a GOAWAY frame
4016 // with maximum last-stream-id value.
4017 // Transactions started before receiving such a GOAWAY frame should succeed,
4018 // but SpdySession should be unavailable for new streams.
TEST_P(SpdyNetworkTransactionTest,GracefulGoaway)4019 TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) {
4020 spdy::SpdySerializedFrame req1(
4021 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4022 spdy_util_.UpdateWithStreamDestruction(1);
4023 spdy::SpdySerializedFrame req2(
4024 spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST));
4025 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
4026
4027 spdy::SpdySerializedFrame resp1(
4028 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4029 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
4030 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4031 0x7fffffff, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown."));
4032 spdy::SpdySerializedFrame resp2(
4033 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4034 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
4035 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
4036 CreateMockRead(goaway, 4), CreateMockRead(resp2, 5),
4037 CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7)};
4038
4039 // Run first transaction.
4040 SequencedSocketData data(reads, writes);
4041 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4042 helper.RunPreTestSetup();
4043 helper.AddData(&data);
4044 helper.RunDefaultTest();
4045
4046 // Verify first response.
4047 TransactionHelperResult out = helper.output();
4048 EXPECT_THAT(out.rv, IsOk());
4049 EXPECT_EQ("HTTP/1.1 200", out.status_line);
4050 EXPECT_EQ("hello!", out.response_data);
4051
4052 // GOAWAY frame has not yet been received, SpdySession should be available.
4053 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4054 SpdySessionKey key(host_port_pair_, ProxyChain::Direct(),
4055 PRIVACY_MODE_DISABLED,
4056 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
4057 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
4058 EXPECT_TRUE(
4059 spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
4060 base::WeakPtr<SpdySession> spdy_session =
4061 spdy_session_pool->FindAvailableSession(
4062 key, /* enable_ip_based_pooling = */ true,
4063 /* is_websocket = */ false, log_);
4064 EXPECT_TRUE(spdy_session);
4065
4066 // Start second transaction.
4067 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4068 TestCompletionCallback callback;
4069 HttpRequestInfo request2;
4070 request2.method = "GET";
4071 request2.url = GURL("https://www.example.org/foo");
4072 request2.traffic_annotation =
4073 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4074 int rv = trans2.Start(&request2, callback.callback(), log_);
4075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4076 rv = callback.WaitForResult();
4077 EXPECT_THAT(rv, IsOk());
4078
4079 // Verify second response.
4080 const HttpResponseInfo* response = trans2.GetResponseInfo();
4081 ASSERT_TRUE(response);
4082 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response->connection_info);
4083 ASSERT_TRUE(response->headers);
4084 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
4085 EXPECT_TRUE(response->was_fetched_via_spdy);
4086 EXPECT_TRUE(response->was_alpn_negotiated);
4087 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4088 EXPECT_EQ(443, response->remote_endpoint.port());
4089 std::string response_data;
4090 rv = ReadTransaction(&trans2, &response_data);
4091 EXPECT_THAT(rv, IsOk());
4092 EXPECT_EQ("hello!", response_data);
4093
4094 // Graceful GOAWAY was received, SpdySession should be unavailable.
4095 EXPECT_FALSE(
4096 spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
4097 spdy_session = spdy_session_pool->FindAvailableSession(
4098 key, /* enable_ip_based_pooling = */ true,
4099 /* is_websocket = */ false, log_);
4100 EXPECT_FALSE(spdy_session);
4101
4102 helper.VerifyDataConsumed();
4103 }
4104
4105 // Verify that an active stream with ID not exceeding the Last-Stream-ID field
4106 // of the incoming GOAWAY frame can receive data both before and after the
4107 // GOAWAY frame.
TEST_P(SpdyNetworkTransactionTest,ActiveStreamWhileGoingAway)4108 TEST_P(SpdyNetworkTransactionTest, ActiveStreamWhileGoingAway) {
4109 spdy::SpdySerializedFrame req(
4110 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4111 MockWrite writes[] = {CreateMockWrite(req, 0)};
4112
4113 spdy::SpdySerializedFrame resp(
4114 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4115 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4116 /* last_good_stream_id = */ 1, spdy::ERROR_CODE_NO_ERROR,
4117 "Graceful shutdown."));
4118 spdy::SpdySerializedFrame body1(
4119 spdy_util_.ConstructSpdyDataFrame(1, "foo", false));
4120 spdy::SpdySerializedFrame body2(
4121 spdy_util_.ConstructSpdyDataFrame(1, "bar", true));
4122 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body1, 2),
4123 CreateMockRead(goaway, 3), CreateMockRead(body2, 4),
4124 MockRead(ASYNC, 0, 5)};
4125
4126 SequencedSocketData data(reads, writes);
4127 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4128 helper.AddData(&data);
4129
4130 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
4131 TestCompletionCallback callback;
4132 int rv = trans.Start(&request_, callback.callback(), log_);
4133 EXPECT_THAT(callback.GetResult(rv), IsOk());
4134
4135 base::RunLoop().RunUntilIdle();
4136 helper.VerifyDataConsumed();
4137
4138 const HttpResponseInfo* response = trans.GetResponseInfo();
4139 ASSERT_TRUE(response);
4140 EXPECT_TRUE(response->was_fetched_via_spdy);
4141
4142 ASSERT_TRUE(response->headers);
4143 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
4144
4145 std::string response_data;
4146 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
4147 EXPECT_EQ("foobar", response_data);
4148 }
4149
TEST_P(SpdyNetworkTransactionTest,CloseWithActiveStream)4150 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4151 spdy::SpdySerializedFrame req(
4152 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4153 MockWrite writes[] = {CreateMockWrite(req, 0)};
4154
4155 spdy::SpdySerializedFrame resp(
4156 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4157 MockRead reads[] = {
4158 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
4159 };
4160
4161 SequencedSocketData data(reads, writes);
4162
4163 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4164 helper.RunPreTestSetup();
4165 helper.AddData(&data);
4166 helper.StartDefaultTest();
4167 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
4168
4169 helper.WaitForCallbackToComplete();
4170 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
4171
4172 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4173 EXPECT_TRUE(response->headers);
4174 EXPECT_TRUE(response->was_fetched_via_spdy);
4175
4176 // Verify that we consumed all test data.
4177 helper.VerifyDataConsumed();
4178 }
4179
TEST_P(SpdyNetworkTransactionTest,GoAwayImmediately)4180 TEST_P(SpdyNetworkTransactionTest, GoAwayImmediately) {
4181 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
4182 MockRead reads[] = {CreateMockRead(goaway, 0, SYNCHRONOUS)};
4183 SequencedSocketData data(reads, base::span<MockWrite>());
4184
4185 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4186 helper.RunPreTestSetup();
4187 helper.AddData(&data);
4188 helper.StartDefaultTest();
4189 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
4190
4191 helper.WaitForCallbackToComplete();
4192 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
4193
4194 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4195 EXPECT_FALSE(response->headers);
4196 EXPECT_TRUE(response->was_fetched_via_spdy);
4197
4198 // Verify that we consumed all test data.
4199 helper.VerifyDataConsumed();
4200 }
4201
4202 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4203 // protocol negotiation happens, instead this test forces protocols for both
4204 // sockets.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredRetry)4205 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4206 request_.method = "GET";
4207 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4208 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4209
4210 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4211 spdy::Http2HeaderBlock headers(
4212 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
4213 spdy::SpdySerializedFrame req(
4214 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
4215 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4216 spdy::SpdySerializedFrame rst(
4217 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4218 MockRead reads0[] = {CreateMockRead(rst, 1)};
4219 SequencedSocketData data0(reads0, writes0);
4220
4221 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4222 // Expect HTTP/2 protocols too in SSLConfig.
4223 ssl_provider0->next_protos_expected_in_ssl_config =
4224 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4225 // Force SPDY.
4226 ssl_provider0->next_proto = kProtoHTTP2;
4227 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
4228
4229 // Second socket: falling back to HTTP/1.1.
4230 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4231 "GET / HTTP/1.1\r\n"
4232 "Host: www.example.org\r\n"
4233 "Connection: keep-alive\r\n\r\n")};
4234 MockRead reads1[] = {MockRead(ASYNC, 1,
4235 "HTTP/1.1 200 OK\r\n"
4236 "Content-Length: 5\r\n\r\n"
4237 "hello")};
4238 SequencedSocketData data1(reads1, writes1);
4239
4240 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4241 // Expect only HTTP/1.1 protocol in SSLConfig.
4242 ssl_provider1->next_protos_expected_in_ssl_config =
4243 NextProtoVector{kProtoHTTP11};
4244 // Force HTTP/1.1.
4245 ssl_provider1->next_proto = kProtoHTTP11;
4246 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
4247
4248 HttpServerProperties* http_server_properties =
4249 helper.session()->spdy_session_pool()->http_server_properties();
4250 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4251 url::SchemeHostPort(request_.url), NetworkAnonymizationKey()));
4252
4253 helper.RunPreTestSetup();
4254 helper.StartDefaultTest();
4255 helper.FinishDefaultTestWithoutVerification();
4256 helper.VerifyDataConsumed();
4257 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4258 url::SchemeHostPort(request_.url), NetworkAnonymizationKey()));
4259
4260 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4261 ASSERT_TRUE(response);
4262 ASSERT_TRUE(response->headers);
4263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4264 EXPECT_FALSE(response->was_fetched_via_spdy);
4265 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4266 EXPECT_TRUE(response->was_alpn_negotiated);
4267 EXPECT_TRUE(request_.url.SchemeIs("https"));
4268 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4269 EXPECT_EQ(443, response->remote_endpoint.port());
4270 std::string response_data;
4271 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
4272 EXPECT_EQ("hello", response_data);
4273 }
4274
4275 // Same as above test, but checks that NetworkAnonymizationKeys are respected.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredRetryWithNetworkAnonymizationKey)4276 TEST_P(SpdyNetworkTransactionTest,
4277 HTTP11RequiredRetryWithNetworkAnonymizationKey) {
4278 const SchemefulSite kSite1(GURL("https://foo.test/"));
4279 const SchemefulSite kSite2(GURL("https://bar.test/"));
4280 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4281 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
4282
4283 const NetworkIsolationKey kNetworkIsolationKeys[] = {
4284 kNetworkIsolationKey1, kNetworkIsolationKey2, NetworkIsolationKey()};
4285
4286 base::test::ScopedFeatureList feature_list;
4287 feature_list.InitWithFeatures(
4288 // enabled_features
4289 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
4290 // Need to partition connections by NetworkAnonymizationKey for
4291 // SpdySessionKeys to include NetworkAnonymizationKeys.
4292 features::kPartitionConnectionsByNetworkIsolationKey},
4293 // disabled_features
4294 {});
4295
4296 // Do not force SPDY so that sockets can negotiate HTTP/1.1.
4297 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4298
4299 // For each server, set up and tear down a QUIC session cleanly, and check
4300 // that stats have been added to HttpServerProperties using the correct
4301 // NetworkAnonymizationKey.
4302 for (size_t i = 0; i < std::size(kNetworkIsolationKeys); ++i) {
4303 SCOPED_TRACE(i);
4304
4305 request_.method = "GET";
4306 request_.network_isolation_key = kNetworkIsolationKeys[i];
4307 request_.network_anonymization_key =
4308 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
4309 kNetworkIsolationKeys[i]);
4310
4311 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4312 SpdyTestUtil spdy_util(/*use_priority_header=*/true);
4313 spdy::Http2HeaderBlock headers(
4314 spdy_util.ConstructGetHeaderBlock(kDefaultUrl));
4315 spdy::SpdySerializedFrame req(
4316 spdy_util.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
4317 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4318 spdy::SpdySerializedFrame rst(spdy_util.ConstructSpdyRstStream(
4319 1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4320 MockRead reads0[] = {CreateMockRead(rst, 1)};
4321 SequencedSocketData data0(reads0, writes0);
4322
4323 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4324 // Expect HTTP/2 protocols too in SSLConfig.
4325 ssl_provider0->next_protos_expected_in_ssl_config =
4326 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4327 // Force SPDY.
4328 ssl_provider0->next_proto = kProtoHTTP2;
4329 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
4330
4331 // Second socket: falling back to HTTP/1.1.
4332 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4333 "GET / HTTP/1.1\r\n"
4334 "Host: www.example.org\r\n"
4335 "Connection: keep-alive\r\n\r\n")};
4336 MockRead reads1[] = {MockRead(ASYNC, 1,
4337 "HTTP/1.1 200 OK\r\n"
4338 "Content-Length: 5\r\n\r\n"
4339 "hello")};
4340 SequencedSocketData data1(reads1, writes1);
4341
4342 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4343 // Expect only HTTP/1.1 protocol in SSLConfig.
4344 ssl_provider1->next_protos_expected_in_ssl_config =
4345 NextProtoVector{kProtoHTTP11};
4346 // Force HTTP/1.1.
4347 ssl_provider1->next_proto = kProtoHTTP11;
4348 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
4349
4350 HttpServerProperties* http_server_properties =
4351 helper.session()->spdy_session_pool()->http_server_properties();
4352 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4353 url::SchemeHostPort(request_.url),
4354 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
4355 kNetworkIsolationKeys[i])));
4356
4357 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
4358
4359 TestCompletionCallback callback;
4360 int rv = trans.Start(&request_, callback.callback(), log_);
4361 EXPECT_THAT(callback.GetResult(rv), IsOk());
4362
4363 const HttpResponseInfo* response = trans.GetResponseInfo();
4364 ASSERT_TRUE(response);
4365 ASSERT_TRUE(response->headers);
4366 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4367 EXPECT_FALSE(response->was_fetched_via_spdy);
4368 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4369 EXPECT_TRUE(response->was_alpn_negotiated);
4370 EXPECT_TRUE(request_.url.SchemeIs("https"));
4371 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4372 EXPECT_EQ(443, response->remote_endpoint.port());
4373 std::string response_data;
4374 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
4375 EXPECT_EQ("hello", response_data);
4376
4377 for (size_t j = 0; j < std::size(kNetworkIsolationKeys); ++j) {
4378 // NetworkAnonymizationKeys up to kNetworkIsolationKeys[j] are known
4379 // to require HTTP/1.1, others are not.
4380 if (j <= i) {
4381 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4382 url::SchemeHostPort(request_.url),
4383 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
4384 kNetworkIsolationKeys[j])));
4385 } else {
4386 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4387 url::SchemeHostPort(request_.url),
4388 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
4389 kNetworkIsolationKeys[j])));
4390 }
4391 }
4392 }
4393 }
4394
4395 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4396 // proxy. Note that no actual protocol negotiation happens, instead this test
4397 // forces protocols for both sockets.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredProxyRetry)4398 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4399 request_.method = "GET";
4400 auto session_deps = std::make_unique<SpdySessionDependencies>(
4401 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4402 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
4403 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4404 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4405 std::move(session_deps));
4406
4407 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4408 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
4409 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
4410 HostPortPair("www.example.org", 443)));
4411 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4412 spdy::SpdySerializedFrame rst(
4413 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4414 MockRead reads0[] = {CreateMockRead(rst, 1)};
4415 SequencedSocketData data0(reads0, writes0);
4416
4417 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4418 // Expect HTTP/2 protocols too in SSLConfig.
4419 ssl_provider0->next_protos_expected_in_ssl_config =
4420 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4421 // Force SPDY.
4422 ssl_provider0->next_proto = kProtoHTTP2;
4423 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
4424
4425 // Second socket: retry using HTTP/1.1.
4426 MockWrite writes1[] = {
4427 MockWrite(ASYNC, 0,
4428 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4429 "Host: www.example.org:443\r\n"
4430 "Proxy-Connection: keep-alive\r\n\r\n"),
4431 MockWrite(ASYNC, 2,
4432 "GET / HTTP/1.1\r\n"
4433 "Host: www.example.org\r\n"
4434 "Connection: keep-alive\r\n\r\n"),
4435 };
4436
4437 MockRead reads1[] = {
4438 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4439 MockRead(ASYNC, 3,
4440 "HTTP/1.1 200 OK\r\n"
4441 "Content-Length: 5\r\n\r\n"
4442 "hello"),
4443 };
4444 SequencedSocketData data1(reads1, writes1);
4445
4446 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4447 // Expect only HTTP/1.1 protocol in SSLConfig.
4448 ssl_provider1->next_protos_expected_in_ssl_config =
4449 NextProtoVector{kProtoHTTP11};
4450 // Force HTTP/1.1.
4451 ssl_provider1->next_proto = kProtoHTTP11;
4452 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
4453
4454 // A third socket is needed for the tunnelled connection.
4455 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4456 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4457 ssl_provider2.get());
4458
4459 HttpServerProperties* http_server_properties =
4460 helper.session()->spdy_session_pool()->http_server_properties();
4461 url::SchemeHostPort proxy_scheme_host_port(url::kHttpsScheme, "myproxy", 70);
4462 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4463 proxy_scheme_host_port, NetworkAnonymizationKey()));
4464
4465 helper.RunPreTestSetup();
4466 helper.StartDefaultTest();
4467 helper.FinishDefaultTestWithoutVerification();
4468 helper.VerifyDataConsumed();
4469 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4470 proxy_scheme_host_port, NetworkAnonymizationKey()));
4471
4472 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4473 ASSERT_TRUE(response);
4474 ASSERT_TRUE(response->headers);
4475 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4476 EXPECT_FALSE(response->was_fetched_via_spdy);
4477 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4478 EXPECT_FALSE(response->was_alpn_negotiated);
4479 EXPECT_TRUE(request_.url.SchemeIs("https"));
4480 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4481 EXPECT_EQ(70, response->remote_endpoint.port());
4482 std::string response_data;
4483 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
4484 EXPECT_EQ("hello", response_data);
4485 }
4486
4487 // Same as above, but also test that NetworkAnonymizationKeys are respected.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredProxyRetryWithNetworkAnonymizationKey)4488 TEST_P(SpdyNetworkTransactionTest,
4489 HTTP11RequiredProxyRetryWithNetworkAnonymizationKey) {
4490 const SchemefulSite kSite1(GURL("https://foo.test/"));
4491 const SchemefulSite kSite2(GURL("https://bar.test/"));
4492 const auto kNetworkAnonymizationKey1 =
4493 NetworkAnonymizationKey::CreateSameSite(kSite1);
4494 const auto kNetworkAnonymizationKey2 =
4495 NetworkAnonymizationKey::CreateSameSite(kSite2);
4496 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4497 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
4498
4499 const NetworkAnonymizationKey kNetworkAnonymizationKeys[] = {
4500 kNetworkAnonymizationKey1, kNetworkAnonymizationKey2,
4501 NetworkAnonymizationKey()};
4502 const NetworkIsolationKey kNetworkIsolationKeys[] = {
4503 kNetworkIsolationKey1, kNetworkIsolationKey2, NetworkIsolationKey()};
4504
4505 base::test::ScopedFeatureList feature_list;
4506 feature_list.InitWithFeatures(
4507 // enabled_features
4508 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
4509 // Need to partition connections by NetworkAnonymizationKey for
4510 // SpdySessionKeys to include NetworkAnonymizationKeys.
4511 features::kPartitionConnectionsByNetworkIsolationKey},
4512 // disabled_features
4513 {});
4514
4515 request_.method = "GET";
4516 auto session_deps = std::make_unique<SpdySessionDependencies>(
4517 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4518 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
4519 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4520 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4521 std::move(session_deps));
4522 helper.RunPreTestSetup();
4523
4524 for (size_t i = 0; i < std::size(kNetworkAnonymizationKeys); ++i) {
4525 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4526
4527 SpdyTestUtil spdy_util(/*use_priority_header=*/true);
4528 spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyConnect(
4529 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
4530 HostPortPair("www.example.org", 443)));
4531 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4532 spdy::SpdySerializedFrame rst(spdy_util.ConstructSpdyRstStream(
4533 1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4534 MockRead reads0[] = {CreateMockRead(rst, 1)};
4535 SequencedSocketData data0(reads0, writes0);
4536
4537 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4538 // Expect HTTP/2 protocols too in SSLConfig.
4539 ssl_provider0->next_protos_expected_in_ssl_config =
4540 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4541 // Force SPDY.
4542 ssl_provider0->next_proto = kProtoHTTP2;
4543 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
4544
4545 // Second socket: retry using HTTP/1.1.
4546 MockWrite writes1[] = {
4547 MockWrite(ASYNC, 0,
4548 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4549 "Host: www.example.org:443\r\n"
4550 "Proxy-Connection: keep-alive\r\n\r\n"),
4551 MockWrite(ASYNC, 2,
4552 "GET / HTTP/1.1\r\n"
4553 "Host: www.example.org\r\n"
4554 "Connection: keep-alive\r\n\r\n"),
4555 };
4556
4557 MockRead reads1[] = {
4558 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4559 MockRead(ASYNC, 3,
4560 "HTTP/1.1 200 OK\r\n"
4561 "Content-Length: 5\r\n\r\n"
4562 "hello"),
4563 };
4564 SequencedSocketData data1(reads1, writes1);
4565
4566 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4567 // Expect only HTTP/1.1 protocol in SSLConfig.
4568 ssl_provider1->next_protos_expected_in_ssl_config =
4569 NextProtoVector{kProtoHTTP11};
4570 // Force HTTP/1.1.
4571 ssl_provider1->next_proto = kProtoHTTP11;
4572 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
4573
4574 // A third socket is needed for the tunnelled connection.
4575 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4576 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4577 ssl_provider2.get());
4578
4579 HttpServerProperties* http_server_properties =
4580 helper.session()->spdy_session_pool()->http_server_properties();
4581 url::SchemeHostPort proxy_scheme_host_port(url::kHttpsScheme, "myproxy",
4582 70);
4583 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4584 proxy_scheme_host_port, kNetworkAnonymizationKeys[i]));
4585
4586 request_.network_isolation_key = kNetworkIsolationKeys[i];
4587 request_.network_anonymization_key = kNetworkAnonymizationKeys[i];
4588 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
4589 TestCompletionCallback callback;
4590 int rv = trans.Start(&request_, callback.callback(), log_);
4591 EXPECT_THAT(callback.GetResult(rv), IsOk());
4592 helper.VerifyDataConsumed();
4593
4594 const HttpResponseInfo* response = trans.GetResponseInfo();
4595 ASSERT_TRUE(response);
4596 ASSERT_TRUE(response->headers);
4597 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4598 EXPECT_FALSE(response->was_fetched_via_spdy);
4599 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4600 EXPECT_FALSE(response->was_alpn_negotiated);
4601 EXPECT_TRUE(request_.url.SchemeIs("https"));
4602 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4603 EXPECT_EQ(70, response->remote_endpoint.port());
4604 std::string response_data;
4605 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
4606 EXPECT_EQ("hello", response_data);
4607
4608 for (size_t j = 0; j < std::size(kNetworkAnonymizationKeys); ++j) {
4609 // The proxy SchemeHostPort URL should not be marked as requiring HTTP/1.1
4610 // using the current NetworkAnonymizationKey, and the state of others
4611 // should be unchanged since the last loop iteration..
4612 if (j <= i) {
4613 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4614 proxy_scheme_host_port, kNetworkAnonymizationKeys[j]));
4615 } else {
4616 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4617 proxy_scheme_host_port, kNetworkAnonymizationKeys[j]));
4618 }
4619 }
4620
4621 // The destination SchemeHostPort should not be marked as requiring
4622 // HTTP/1.1.
4623 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4624 url::SchemeHostPort(request_.url), kNetworkAnonymizationKeys[i]));
4625 }
4626 }
4627
4628 // Same as HTTP11RequiredProxyRetry above except for nested proxies where
4629 // HTTP_1_1_REQUIRED is received from the first proxy in the chain.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredNestedProxyFirstProxyRetry)4630 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredNestedProxyFirstProxyRetry) {
4631 request_.method = "GET";
4632
4633 // Configure a nested proxy.
4634 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
4635 HostPortPair("proxy1.test", 70)};
4636 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
4637 HostPortPair("proxy2.test", 71)};
4638 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
4639
4640 ProxyList proxy_list;
4641 proxy_list.AddProxyChain(kNestedProxyChain);
4642 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
4643
4644 auto session_deps = std::make_unique<SpdySessionDependencies>(
4645 ConfiguredProxyResolutionService::CreateFixedForTest(
4646 ProxyConfigWithAnnotation(proxy_config,
4647 TRAFFIC_ANNOTATION_FOR_TESTS)));
4648 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4649 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4650 std::move(session_deps));
4651
4652 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4653 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
4654 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
4655 kProxyServer2.host_port_pair()));
4656 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4657 spdy::SpdySerializedFrame rst(
4658 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4659 MockRead reads0[] = {CreateMockRead(rst, 1)};
4660 SequencedSocketData data0(reads0, writes0);
4661
4662 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4663 // Expect HTTP/2 protocols too in SSLConfig.
4664 ssl_provider0->next_protos_expected_in_ssl_config =
4665 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4666 // Force SPDY.
4667 ssl_provider0->next_proto = kProtoHTTP2;
4668 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
4669
4670 // Second socket: retry using HTTP/1.1.
4671 MockWrite writes1[] = {
4672 MockWrite(ASYNC, 0,
4673 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
4674 "Host: proxy2.test:71\r\n"
4675 "Proxy-Connection: keep-alive\r\n\r\n"),
4676 MockWrite(ASYNC, 2,
4677 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4678 "Host: www.example.org:443\r\n"
4679 "Proxy-Connection: keep-alive\r\n\r\n"),
4680 MockWrite(ASYNC, 4,
4681 "GET / HTTP/1.1\r\n"
4682 "Host: www.example.org\r\n"
4683 "Connection: keep-alive\r\n\r\n"),
4684 };
4685
4686 MockRead reads1[] = {
4687 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4688 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
4689 MockRead(ASYNC, 5,
4690 "HTTP/1.1 200 OK\r\n"
4691 "Content-Length: 5\r\n\r\n"
4692 "hello"),
4693 };
4694 SequencedSocketData data1(reads1, writes1);
4695
4696 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4697 // Expect only HTTP/1.1 protocol in SSLConfig.
4698 ssl_provider1->next_protos_expected_in_ssl_config =
4699 NextProtoVector{kProtoHTTP11};
4700 // Force HTTP/1.1.
4701 ssl_provider1->next_proto = kProtoHTTP11;
4702 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
4703
4704 // A third and fourth socket are needed for the connection to the second hop
4705 // and for the tunnelled GET request.
4706 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4707 ssl_provider2->next_protos_expected_in_ssl_config =
4708 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4709 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4710 ssl_provider2.get());
4711 auto ssl_provider3 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4712 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4713 ssl_provider3.get());
4714
4715 HttpServerProperties* http_server_properties =
4716 helper.session()->spdy_session_pool()->http_server_properties();
4717 url::SchemeHostPort proxy_scheme_host_port(
4718 url::kHttpsScheme, kProxyServer1.host_port_pair().host(),
4719 kProxyServer1.host_port_pair().port());
4720 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4721 proxy_scheme_host_port, NetworkAnonymizationKey()));
4722
4723 helper.RunPreTestSetup();
4724 helper.StartDefaultTest();
4725 helper.FinishDefaultTestWithoutVerification();
4726 helper.VerifyDataConsumed();
4727 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4728 proxy_scheme_host_port, NetworkAnonymizationKey()));
4729
4730 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4731 ASSERT_TRUE(response);
4732 ASSERT_TRUE(response->headers);
4733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4734 EXPECT_FALSE(response->was_fetched_via_spdy);
4735 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4736 EXPECT_FALSE(response->was_alpn_negotiated);
4737 EXPECT_TRUE(request_.url.SchemeIs("https"));
4738 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4739 EXPECT_EQ(70, response->remote_endpoint.port());
4740 std::string response_data;
4741 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
4742 EXPECT_EQ("hello", response_data);
4743 }
4744
4745 // Same as above except for nested proxies where HTTP_1_1_REQUIRED is received
4746 // from the second proxy in the chain.
TEST_P(SpdyNetworkTransactionTest,HTTP11RequiredNestedProxySecondProxyRetry)4747 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredNestedProxySecondProxyRetry) {
4748 request_.method = "GET";
4749
4750 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
4751 HostPortPair("proxy1.test", 70)};
4752 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
4753 HostPortPair("proxy2.test", 71)};
4754 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
4755
4756 ProxyList proxy_list;
4757 proxy_list.AddProxyChain(kNestedProxyChain);
4758 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
4759
4760 auto session_deps = std::make_unique<SpdySessionDependencies>(
4761 ConfiguredProxyResolutionService::CreateFixedForTest(
4762 ProxyConfigWithAnnotation(proxy_config,
4763 TRAFFIC_ANNOTATION_FOR_TESTS)));
4764 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4765 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4766 std::move(session_deps));
4767
4768 // CONNECT to proxy2.test:71 via SPDY.
4769 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
4770 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
4771 kProxyServer2.host_port_pair()));
4772
4773 spdy::SpdySerializedFrame proxy2_connect_resp(
4774 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4775
4776 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
4777 // request is calculated correctly.
4778 SpdyTestUtil new_spdy_util;
4779 // HTTP/2 endpoint CONNECT rejected with HTTP_1_1_REQUIRED.
4780 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
4781 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
4782 HostPortPair("www.example.org", 443)));
4783 spdy::SpdySerializedFrame server_rst(new_spdy_util.ConstructSpdyRstStream(
4784 1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
4785 spdy::SpdySerializedFrame client_rst(
4786 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
4787
4788 // Since this request and response are sent over the tunnel established
4789 // previously, from a socket-perspective these need to be wrapped as data
4790 // frames.
4791 spdy::SpdySerializedFrame wrapped_endpoint_connect(
4792 new_spdy_util.ConstructSpdyDataFrame(1, endpoint_connect, false));
4793 spdy::SpdySerializedFrame wrapped_server_rst(
4794 new_spdy_util.ConstructSpdyDataFrame(1, server_rst, /*fin=*/true));
4795
4796 MockWrite writes0[] = {
4797 CreateMockWrite(proxy2_connect, 0),
4798 CreateMockWrite(wrapped_endpoint_connect, 2),
4799 CreateMockWrite(client_rst, 5),
4800 };
4801
4802 MockRead reads0[] = {
4803 CreateMockRead(proxy2_connect_resp, 1),
4804 CreateMockRead(wrapped_server_rst, 3),
4805 MockRead(ASYNC, 0, 4),
4806 };
4807
4808 SequencedSocketData data0(reads0, writes0);
4809
4810 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4811 // Expect HTTP/2 protocols too in SSLConfig.
4812 ssl_provider0->next_protos_expected_in_ssl_config =
4813 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4814 ssl_provider0->next_proto = kProtoHTTP2;
4815 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4816 ssl_provider0.get());
4817
4818 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4819 ssl_provider1->next_protos_expected_in_ssl_config =
4820 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4821 // Force SPDY.
4822 ssl_provider1->next_proto = kProtoHTTP2;
4823 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider1));
4824
4825 // Second socket: retry using HTTP/1.1.
4826 MockWrite writes1[] = {
4827 MockWrite(ASYNC, 0,
4828 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
4829 "Host: proxy2.test:71\r\n"
4830 "Proxy-Connection: keep-alive\r\n\r\n"),
4831 MockWrite(ASYNC, 2,
4832 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4833 "Host: www.example.org:443\r\n"
4834 "Proxy-Connection: keep-alive\r\n\r\n"),
4835 MockWrite(ASYNC, 4,
4836 "GET / HTTP/1.1\r\n"
4837 "Host: www.example.org\r\n"
4838 "Connection: keep-alive\r\n\r\n"),
4839 };
4840
4841 MockRead reads1[] = {
4842 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4843 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
4844 MockRead(ASYNC, 5,
4845 "HTTP/1.1 200 OK\r\n"
4846 "Content-Length: 5\r\n\r\n"
4847 "hello"),
4848 };
4849 SequencedSocketData data1(reads1, writes1);
4850
4851 // Create a new SSLSocketDataProvider for the new connection to the first
4852 // proxy.
4853 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4854 // Force HTTP/1.1 for the reconnection to the first proxy for simplicity.
4855 ssl_provider2->next_protos_expected_in_ssl_config =
4856 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
4857 ssl_provider2->next_proto = kProtoHTTP11;
4858 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider2));
4859
4860 // Create a new SSLSocketDataProvider for the new connection to the second
4861 // proxy.
4862 auto ssl_provider3 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4863 // Expect only HTTP/1.1 protocol in the SSLConfig for the second proxy.
4864 ssl_provider3->next_protos_expected_in_ssl_config =
4865 NextProtoVector{kProtoHTTP11};
4866 // Force HTTP/1.1.
4867 ssl_provider3->next_proto = kProtoHTTP11;
4868 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4869 ssl_provider3.get());
4870
4871 // One final SSL provider for the connection through the proxy.
4872 auto ssl_provider4 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
4873 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4874 ssl_provider4.get());
4875
4876 HttpServerProperties* http_server_properties =
4877 helper.session()->spdy_session_pool()->http_server_properties();
4878 url::SchemeHostPort proxy_scheme_host_port(
4879 url::kHttpsScheme, kProxyServer2.host_port_pair().host(),
4880 kProxyServer2.host_port_pair().port());
4881 EXPECT_FALSE(http_server_properties->RequiresHTTP11(
4882 proxy_scheme_host_port, NetworkAnonymizationKey()));
4883
4884 helper.RunPreTestSetup();
4885 helper.StartDefaultTest();
4886 helper.FinishDefaultTestWithoutVerification();
4887 helper.VerifyDataConsumed();
4888 EXPECT_TRUE(http_server_properties->RequiresHTTP11(
4889 proxy_scheme_host_port, NetworkAnonymizationKey()));
4890
4891 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4892 ASSERT_TRUE(response);
4893 ASSERT_TRUE(response->headers);
4894 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4895 EXPECT_FALSE(response->was_fetched_via_spdy);
4896 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
4897 EXPECT_FALSE(response->was_alpn_negotiated);
4898 EXPECT_TRUE(request_.url.SchemeIs("https"));
4899 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4900 EXPECT_EQ(70, response->remote_endpoint.port());
4901 std::string response_data;
4902 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
4903 EXPECT_EQ("hello", response_data);
4904 }
4905
4906 // Test to make sure we can correctly connect through a proxy.
TEST_P(SpdyNetworkTransactionTest,ProxyConnect)4907 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4908 auto session_deps = std::make_unique<SpdySessionDependencies>(
4909 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4910 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
4911 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4912 std::move(session_deps));
4913 helper.RunPreTestSetup();
4914 HttpNetworkTransaction* trans = helper.trans();
4915
4916 const char kConnect443[] = {
4917 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4918 "Host: www.example.org:443\r\n"
4919 "Proxy-Connection: keep-alive\r\n\r\n"};
4920 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4921 spdy::SpdySerializedFrame req(
4922 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4923 spdy::SpdySerializedFrame resp(
4924 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4925 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
4926
4927 MockWrite writes[] = {
4928 MockWrite(SYNCHRONOUS, kConnect443, std::size(kConnect443) - 1, 0),
4929 CreateMockWrite(req, 2),
4930 };
4931 MockRead reads[] = {
4932 MockRead(SYNCHRONOUS, kHTTP200, std::size(kHTTP200) - 1, 1),
4933 CreateMockRead(resp, 3),
4934 CreateMockRead(body, 4),
4935 MockRead(ASYNC, nullptr, 0, 5),
4936 };
4937 SequencedSocketData data(reads, writes);
4938
4939 helper.AddData(&data);
4940 TestCompletionCallback callback;
4941
4942 int rv = trans->Start(&request_, callback.callback(), log_);
4943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4944
4945 rv = callback.WaitForResult();
4946 EXPECT_EQ(0, rv);
4947
4948 // Verify the response headers.
4949 HttpResponseInfo response = *trans->GetResponseInfo();
4950 ASSERT_TRUE(response.headers);
4951 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
4952
4953 std::string response_data;
4954 ASSERT_THAT(ReadTransaction(trans, &response_data), IsOk());
4955 EXPECT_EQ("hello!", response_data);
4956 helper.VerifyDataConsumed();
4957 }
4958
4959 // Test to make sure we can correctly connect through a proxy to
4960 // www.example.org, if there already exists a direct spdy connection to
4961 // www.example.org. See https://crbug.com/49874.
TEST_P(SpdyNetworkTransactionTest,DirectConnectProxyReconnect)4962 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4963 // Use a proxy service which returns a proxy fallback list from DIRECT to
4964 // myproxy:70. For this test there will be no fallback, so it is equivalent
4965 // to simply DIRECT. The reason for appending the second proxy is to verify
4966 // that the session pool key used does is just "DIRECT".
4967 auto session_deps = std::make_unique<SpdySessionDependencies>(
4968 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4969 "DIRECT; PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
4970 // When setting up the first transaction, we store the SpdySessionPool so that
4971 // we can use the same pool in the second transaction.
4972 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4973 std::move(session_deps));
4974
4975 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4976 helper.RunPreTestSetup();
4977
4978 // Construct and send a simple GET request.
4979 spdy::SpdySerializedFrame req(
4980 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4981 MockWrite writes[] = {
4982 CreateMockWrite(req, 0),
4983 };
4984
4985 spdy::SpdySerializedFrame resp(
4986 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4987 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
4988 MockRead reads[] = {
4989 CreateMockRead(resp, 1), CreateMockRead(body, 2),
4990 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
4991 };
4992 SequencedSocketData data(reads, writes);
4993 helper.AddData(&data);
4994 HttpNetworkTransaction* trans = helper.trans();
4995
4996 TestCompletionCallback callback;
4997 TransactionHelperResult out;
4998 out.rv = trans->Start(&request_, callback.callback(), log_);
4999
5000 EXPECT_EQ(out.rv, ERR_IO_PENDING);
5001 out.rv = callback.WaitForResult();
5002 EXPECT_EQ(out.rv, OK);
5003
5004 const HttpResponseInfo* response = trans->GetResponseInfo();
5005 EXPECT_TRUE(response->headers);
5006 EXPECT_TRUE(response->was_fetched_via_spdy);
5007 out.rv = ReadTransaction(trans, &out.response_data);
5008 EXPECT_THAT(out.rv, IsOk());
5009 out.status_line = response->headers->GetStatusLine();
5010 EXPECT_EQ("HTTP/1.1 200", out.status_line);
5011 EXPECT_EQ("hello!", out.response_data);
5012
5013 // Check that the SpdySession is still in the SpdySessionPool.
5014 SpdySessionKey session_pool_key_direct(
5015 host_port_pair_, ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
5016 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
5017 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
5018 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
5019 SpdySessionKey session_pool_key_proxy(
5020 host_port_pair_,
5021 ProxyUriToProxyChain("www.foo.com", ProxyServer::SCHEME_HTTP),
5022 PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
5023 SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
5024 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
5025
5026 // New SpdyTestUtil instance for the session that will be used for the
5027 // proxy connection.
5028 SpdyTestUtil spdy_util_2(/*use_priority_header=*/true);
5029
5030 // Set up data for the proxy connection.
5031 const char kConnect443[] = {
5032 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5033 "Host: www.example.org:443\r\n"
5034 "Proxy-Connection: keep-alive\r\n\r\n"};
5035 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
5036 spdy::SpdySerializedFrame req2(
5037 spdy_util_2.ConstructSpdyGet(kPushedUrl, 1, LOWEST));
5038 spdy::SpdySerializedFrame resp2(
5039 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
5040 spdy::SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
5041
5042 MockWrite writes2[] = {
5043 MockWrite(SYNCHRONOUS, kConnect443, std::size(kConnect443) - 1, 0),
5044 CreateMockWrite(req2, 2),
5045 };
5046 MockRead reads2[] = {
5047 MockRead(SYNCHRONOUS, kHTTP200, std::size(kHTTP200) - 1, 1),
5048 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
5049 MockRead(ASYNC, 0, 5) // EOF
5050 };
5051
5052 SequencedSocketData data_proxy(reads2, writes2);
5053
5054 // Create another request to www.example.org, but this time through a proxy.
5055 request_.method = "GET";
5056 request_.url = GURL(kPushedUrl);
5057 auto session_deps_proxy = std::make_unique<SpdySessionDependencies>(
5058 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5059 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
5060 NormalSpdyTransactionHelper helper_proxy(request_, DEFAULT_PRIORITY, log_,
5061 std::move(session_deps_proxy));
5062
5063 helper_proxy.RunPreTestSetup();
5064 helper_proxy.AddData(&data_proxy);
5065
5066 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
5067 TestCompletionCallback callback_proxy;
5068 int rv = trans_proxy->Start(&request_, callback_proxy.callback(), log_);
5069 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5070 rv = callback_proxy.WaitForResult();
5071 EXPECT_EQ(0, rv);
5072
5073 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
5074 ASSERT_TRUE(response_proxy.headers);
5075 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
5076
5077 std::string response_data;
5078 ASSERT_THAT(ReadTransaction(trans_proxy, &response_data), IsOk());
5079 EXPECT_EQ("hello!", response_data);
5080
5081 helper_proxy.VerifyDataConsumed();
5082 }
5083
5084 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5085 // on a new connection, if the connection was previously known to be good.
5086 // This can happen when a server reboots without saying goodbye, or when
5087 // we're behind a NAT that masked the RST.
TEST_P(SpdyNetworkTransactionTest,VerifyRetryOnConnectionReset)5088 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
5089 spdy::SpdySerializedFrame resp(
5090 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5091 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5092 MockRead reads[] = {
5093 CreateMockRead(resp, 1),
5094 CreateMockRead(body, 2),
5095 MockRead(ASYNC, ERR_IO_PENDING, 3),
5096 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
5097 };
5098
5099 MockRead reads2[] = {
5100 CreateMockRead(resp, 1), CreateMockRead(body, 2),
5101 MockRead(ASYNC, 0, 3) // EOF
5102 };
5103
5104 spdy::SpdySerializedFrame req(
5105 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5106 // In all cases the connection will be reset before req3 can be
5107 // dispatched, destroying both streams.
5108 spdy_util_.UpdateWithStreamDestruction(1);
5109 spdy::SpdySerializedFrame req3(
5110 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
5111 MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)};
5112 MockWrite writes2[] = {CreateMockWrite(req, 0)};
5113
5114 // This test has a couple of variants.
5115 enum {
5116 // Induce the RST while waiting for our transaction to send.
5117 VARIANT_RST_DURING_SEND_COMPLETION = 0,
5118 // Induce the RST while waiting for our transaction to read.
5119 // In this case, the send completed - everything copied into the SNDBUF.
5120 VARIANT_RST_DURING_READ_COMPLETION = 1
5121 };
5122
5123 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5124 variant <= VARIANT_RST_DURING_READ_COMPLETION; ++variant) {
5125 SequencedSocketData data1(reads,
5126 base::make_span(writes1).first(1 + variant));
5127
5128 SequencedSocketData data2(reads2, writes2);
5129
5130 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
5131 nullptr);
5132 helper.AddData(&data1);
5133 helper.AddData(&data2);
5134 helper.RunPreTestSetup();
5135
5136 for (int i = 0; i < 2; ++i) {
5137 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
5138
5139 TestCompletionCallback callback;
5140 int rv = trans.Start(&request_, callback.callback(), log_);
5141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5142 // On the second transaction, we trigger the RST.
5143 if (i == 1) {
5144 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5145 // Writes to the socket complete asynchronously on SPDY by running
5146 // through the message loop. Complete the write here.
5147 base::RunLoop().RunUntilIdle();
5148 }
5149
5150 // Now schedule the ERR_CONNECTION_RESET.
5151 data1.Resume();
5152 }
5153 rv = callback.WaitForResult();
5154 EXPECT_THAT(rv, IsOk());
5155
5156 const HttpResponseInfo* response = trans.GetResponseInfo();
5157 ASSERT_TRUE(response);
5158 EXPECT_TRUE(response->headers);
5159 EXPECT_TRUE(response->was_fetched_via_spdy);
5160 std::string response_data;
5161 rv = ReadTransaction(&trans, &response_data);
5162 EXPECT_THAT(rv, IsOk());
5163 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
5164 EXPECT_EQ("hello!", response_data);
5165 base::RunLoop().RunUntilIdle();
5166 }
5167
5168 helper.VerifyDataConsumed();
5169 base::RunLoop().RunUntilIdle();
5170 }
5171 }
5172
5173 // Tests that Basic authentication works over SPDY
TEST_P(SpdyNetworkTransactionTest,SpdyBasicAuth)5174 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
5175 // The first request will be a bare GET, the second request will be a
5176 // GET with an Authorization header.
5177 spdy::SpdySerializedFrame req_get(
5178 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5179 // Will be refused for lack of auth.
5180 spdy_util_.UpdateWithStreamDestruction(1);
5181 const char* const kExtraAuthorizationHeaders[] = {"authorization",
5182 "Basic Zm9vOmJhcg=="};
5183 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
5184 kExtraAuthorizationHeaders, std::size(kExtraAuthorizationHeaders) / 2, 3,
5185 LOWEST));
5186 MockWrite spdy_writes[] = {
5187 CreateMockWrite(req_get, 0),
5188 CreateMockWrite(req_get_authorization, 3),
5189 };
5190
5191 // The first response is a 401 authentication challenge, and the second
5192 // response will be a 200 response since the second request includes a valid
5193 // Authorization header.
5194 const char* const kExtraAuthenticationHeaders[] = {"www-authenticate",
5195 "Basic realm=\"MyRealm\""};
5196 spdy::SpdySerializedFrame resp_authentication(
5197 spdy_util_.ConstructSpdyReplyError(
5198 "401", kExtraAuthenticationHeaders,
5199 std::size(kExtraAuthenticationHeaders) / 2, 1));
5200 spdy::SpdySerializedFrame body_authentication(
5201 spdy_util_.ConstructSpdyDataFrame(1, true));
5202 spdy::SpdySerializedFrame resp_data(
5203 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
5204 spdy::SpdySerializedFrame body_data(
5205 spdy_util_.ConstructSpdyDataFrame(3, true));
5206
5207 MockRead spdy_reads[] = {
5208 CreateMockRead(resp_authentication, 1),
5209 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
5210 CreateMockRead(resp_data, 4),
5211 CreateMockRead(body_data, 5),
5212 MockRead(ASYNC, 0, 6),
5213 };
5214
5215 SequencedSocketData data(spdy_reads, spdy_writes);
5216 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5217
5218 helper.RunPreTestSetup();
5219 helper.AddData(&data);
5220 helper.StartDefaultTest();
5221 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
5222
5223 helper.WaitForCallbackToComplete();
5224 EXPECT_THAT(helper.output().rv, IsOk());
5225
5226 // Make sure the response has an auth challenge.
5227 HttpNetworkTransaction* trans = helper.trans();
5228 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5229 ASSERT_TRUE(response_start);
5230 ASSERT_TRUE(response_start->headers);
5231 EXPECT_EQ(401, response_start->headers->response_code());
5232 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5233 const absl::optional<AuthChallengeInfo>& auth_challenge =
5234 response_start->auth_challenge;
5235 ASSERT_TRUE(auth_challenge);
5236 EXPECT_FALSE(auth_challenge->is_proxy);
5237 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
5238 EXPECT_EQ("MyRealm", auth_challenge->realm);
5239
5240 // Restart with a username/password.
5241 AuthCredentials credentials(u"foo", u"bar");
5242 TestCompletionCallback callback_restart;
5243 const int rv_restart =
5244 trans->RestartWithAuth(credentials, callback_restart.callback());
5245 EXPECT_THAT(rv_restart, IsError(ERR_IO_PENDING));
5246 const int rv_restart_complete = callback_restart.WaitForResult();
5247 EXPECT_THAT(rv_restart_complete, IsOk());
5248 // TODO(cbentzel): This is actually the same response object as before, but
5249 // data has changed.
5250 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5251 ASSERT_TRUE(response_restart);
5252 ASSERT_TRUE(response_restart->headers);
5253 EXPECT_EQ(200, response_restart->headers->response_code());
5254 EXPECT_FALSE(response_restart->auth_challenge);
5255 }
5256
TEST_P(SpdyNetworkTransactionTest,ResponseHeadersTwice)5257 TEST_P(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
5258 spdy::SpdySerializedFrame req(
5259 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5260 spdy::SpdySerializedFrame rst(
5261 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
5262 MockWrite writes[] = {
5263 CreateMockWrite(req, 0),
5264 CreateMockWrite(rst, 4),
5265 };
5266
5267 spdy::SpdySerializedFrame stream1_reply(
5268 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5269
5270 spdy::Http2HeaderBlock late_headers;
5271 late_headers["hello"] = "bye";
5272 spdy::SpdySerializedFrame stream1_headers(
5273 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(late_headers),
5274 false));
5275 spdy::SpdySerializedFrame stream1_body(
5276 spdy_util_.ConstructSpdyDataFrame(1, true));
5277 MockRead reads[] = {
5278 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_headers, 2),
5279 CreateMockRead(stream1_body, 3), MockRead(ASYNC, 0, 5) // EOF
5280 };
5281
5282 SequencedSocketData data(reads, writes);
5283 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5284 helper.RunToCompletion(&data);
5285 TransactionHelperResult out = helper.output();
5286 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
5287 }
5288
5289 // Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
5290 // trigger a ERR_HTTP2_PROTOCOL_ERROR because trailing HEADERS must not be
5291 // followed by any DATA frames.
TEST_P(SpdyNetworkTransactionTest,SyncReplyDataAfterTrailers)5292 TEST_P(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
5293 spdy::SpdySerializedFrame req(
5294 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5295 spdy::SpdySerializedFrame rst(
5296 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
5297 MockWrite writes[] = {
5298 CreateMockWrite(req, 0),
5299 CreateMockWrite(rst, 5),
5300 };
5301
5302 spdy::SpdySerializedFrame stream1_reply(
5303 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5304 spdy::SpdySerializedFrame stream1_body(
5305 spdy_util_.ConstructSpdyDataFrame(1, false));
5306
5307 spdy::Http2HeaderBlock late_headers;
5308 late_headers["hello"] = "bye";
5309 spdy::SpdySerializedFrame stream1_headers(
5310 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(late_headers),
5311 false));
5312 spdy::SpdySerializedFrame stream1_body2(
5313 spdy_util_.ConstructSpdyDataFrame(1, true));
5314 MockRead reads[] = {
5315 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
5316 CreateMockRead(stream1_headers, 3), CreateMockRead(stream1_body2, 4),
5317 MockRead(ASYNC, 0, 6) // EOF
5318 };
5319
5320 SequencedSocketData data(reads, writes);
5321 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5322 helper.RunToCompletion(&data);
5323 TransactionHelperResult out = helper.output();
5324 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
5325 }
5326
TEST_P(SpdyNetworkTransactionTest,RetryAfterRefused)5327 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5328 // Construct the request.
5329 spdy::SpdySerializedFrame req(
5330 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5331 // Will be destroyed by the RST before stream 3 starts.
5332 spdy_util_.UpdateWithStreamDestruction(1);
5333 spdy::SpdySerializedFrame req2(
5334 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
5335 MockWrite writes[] = {
5336 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
5337 };
5338
5339 spdy::SpdySerializedFrame refused(
5340 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
5341 spdy::SpdySerializedFrame resp(
5342 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
5343 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
5344 MockRead reads[] = {
5345 CreateMockRead(refused, 1), CreateMockRead(resp, 3),
5346 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5) // EOF
5347 };
5348
5349 SequencedSocketData data(reads, writes);
5350 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5351
5352 helper.RunPreTestSetup();
5353 helper.AddData(&data);
5354
5355 HttpNetworkTransaction* trans = helper.trans();
5356
5357 // Start the transaction with basic parameters.
5358 TestCompletionCallback callback;
5359 int rv = trans->Start(&request_, callback.callback(), log_);
5360 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5361 rv = callback.WaitForResult();
5362 EXPECT_THAT(rv, IsOk());
5363
5364 // Finish async network reads.
5365 base::RunLoop().RunUntilIdle();
5366
5367 // Verify that we consumed all test data.
5368 EXPECT_TRUE(data.AllReadDataConsumed());
5369 EXPECT_TRUE(data.AllWriteDataConsumed());
5370
5371 // Verify the response headers.
5372 HttpResponseInfo response = *trans->GetResponseInfo();
5373 EXPECT_TRUE(response.headers);
5374 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
5375 }
5376
TEST_P(SpdyNetworkTransactionTest,OutOfOrderHeaders)5377 TEST_P(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
5378 // This first request will start to establish the SpdySession.
5379 // Then we will start the second (MEDIUM priority) and then third
5380 // (HIGHEST priority) request in such a way that the third will actually
5381 // start before the second, causing the second to be numbered differently
5382 // than the order they were created.
5383 //
5384 // Note that the requests and responses created below are expectations
5385 // of what the above will produce on the wire, and hence are in the
5386 // initial->HIGHEST->LOWEST priority.
5387 //
5388 // Frames are created by SpdySession just before the write associated
5389 // with the frame is attempted, so stream dependencies will be based
5390 // on the streams alive at the point of the request write attempt. Thus
5391 // req1 is alive when req2 is attempted (during but not after the
5392 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5393 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
5394 spdy::SpdySerializedFrame req1(
5395 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5396 spdy::SpdySerializedFrame req2(
5397 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST));
5398 spdy_util_.UpdateWithStreamDestruction(1);
5399 spdy::SpdySerializedFrame req3(
5400 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM));
5401 MockWrite writes[] = {
5402 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1),
5403 CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
5404 };
5405
5406 spdy::SpdySerializedFrame resp1(
5407 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5408 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
5409 spdy::SpdySerializedFrame resp2(
5410 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
5411 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5412 spdy::SpdySerializedFrame resp3(
5413 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
5414 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
5415 MockRead reads[] = {
5416 CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
5417 CreateMockRead(body1, 4), CreateMockRead(resp2, 7),
5418 CreateMockRead(body2, 8), CreateMockRead(resp3, 9),
5419 CreateMockRead(body3, 10), MockRead(ASYNC, 0, 11) // EOF
5420 };
5421
5422 SequencedSocketData data(reads, writes);
5423 NormalSpdyTransactionHelper helper(request_, LOWEST, log_, nullptr);
5424 helper.RunPreTestSetup();
5425 helper.AddData(&data);
5426
5427 // Start the first transaction to set up the SpdySession
5428 HttpNetworkTransaction* trans = helper.trans();
5429 TestCompletionCallback callback;
5430 int rv = trans->Start(&request_, callback.callback(), log_);
5431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5432
5433 // Run the message loop, but do not allow the write to complete.
5434 // This leaves the SpdySession with a write pending, which prevents
5435 // SpdySession from attempting subsequent writes until this write completes.
5436 base::RunLoop().RunUntilIdle();
5437
5438 // Now, start both new transactions
5439 TestCompletionCallback callback2;
5440 HttpNetworkTransaction trans2(MEDIUM, helper.session());
5441 rv = trans2.Start(&request_, callback2.callback(), log_);
5442 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5443 base::RunLoop().RunUntilIdle();
5444
5445 TestCompletionCallback callback3;
5446 HttpNetworkTransaction trans3(HIGHEST, helper.session());
5447 rv = trans3.Start(&request_, callback3.callback(), log_);
5448 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5449 base::RunLoop().RunUntilIdle();
5450
5451 // We now have two HEADERS frames queued up which will be
5452 // dequeued only once the first write completes, which we
5453 // now allow to happen.
5454 ASSERT_TRUE(data.IsPaused());
5455 data.Resume();
5456 EXPECT_THAT(callback.WaitForResult(), IsOk());
5457
5458 // And now we can allow everything else to run to completion.
5459 data.Resume();
5460 base::RunLoop().RunUntilIdle();
5461 EXPECT_THAT(callback2.WaitForResult(), IsOk());
5462 EXPECT_THAT(callback3.WaitForResult(), IsOk());
5463
5464 helper.VerifyDataConsumed();
5465
5466 // At this point the test is completed and we need to safely destroy
5467 // all allocated structures. Helper stores a transaction that has a
5468 // reference to a stack allocated request, which has a short lifetime,
5469 // and is accessed during the transaction destruction. We need to delete
5470 // the transaction while the request is still a valid object.
5471 helper.ResetTrans();
5472 }
5473
5474 // Test that sent data frames and received WINDOW_UPDATE frames change
5475 // the send_window_size_ correctly.
5476
5477 // WINDOW_UPDATE is different than most other frames in that it can arrive
5478 // while the client is still sending the request body. In order to enforce
5479 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5480 // socket data provider, so that initial read that is done as soon as the
5481 // stream is created, succeeds and schedules another read. This way reads
5482 // and writes are interleaved; after doing a full frame write, SpdyStream
5483 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5484 // Once our WINDOW_UPDATE is read, we cannot send HEADERS right away
5485 // since request has not been completely written, therefore we feed
5486 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5487 // write, leading to a complete write of request body; after that we send
5488 // a reply with a body, to cause a graceful shutdown.
5489
5490 // TODO(agayev): develop a socket data provider where both, reads and
5491 // writes are ordered so that writing tests like these are easy and rewrite
5492 // all these tests using it. Right now we are working around the
5493 // limitations as described above and it's not deterministic, tests may
5494 // fail under specific circumstances.
TEST_P(SpdyNetworkTransactionTest,WindowUpdateReceived)5495 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5496 static int kFrameCount = 2;
5497 std::string content(kMaxSpdyFrameChunkSize, 'a');
5498 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
5499 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
5500 0));
5501 spdy::SpdySerializedFrame body(
5502 spdy_util_.ConstructSpdyDataFrame(1, content, false));
5503 spdy::SpdySerializedFrame body_end(
5504 spdy_util_.ConstructSpdyDataFrame(1, content, true));
5505
5506 MockWrite writes[] = {
5507 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
5508 CreateMockWrite(body_end, 2),
5509 };
5510
5511 static const int32_t kDeltaWindowSize = 0xff;
5512 static const int kDeltaCount = 4;
5513 spdy::SpdySerializedFrame window_update(
5514 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5515 spdy::SpdySerializedFrame window_update_dummy(
5516 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5517 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
5518 MockRead reads[] = {
5519 CreateMockRead(window_update_dummy, 3),
5520 CreateMockRead(window_update_dummy, 4),
5521 CreateMockRead(window_update_dummy, 5),
5522 CreateMockRead(window_update, 6), // Four updates, therefore window
5523 CreateMockRead(window_update, 7), // size should increase by
5524 CreateMockRead(window_update, 8), // kDeltaWindowSize * 4
5525 CreateMockRead(window_update, 9),
5526 CreateMockRead(resp, 10),
5527 MockRead(ASYNC, ERR_IO_PENDING, 11),
5528 CreateMockRead(body_end, 12),
5529 MockRead(ASYNC, 0, 13) // EOF
5530 };
5531
5532 SequencedSocketData data(reads, writes);
5533
5534 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
5535 for (int i = 0; i < kFrameCount; ++i) {
5536 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
5537 content.data(), content.size()));
5538 }
5539 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
5540
5541 // Setup the request.
5542 request_.method = "POST";
5543 request_.upload_data_stream = &upload_data_stream;
5544
5545 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5546 helper.AddData(&data);
5547 helper.RunPreTestSetup();
5548
5549 HttpNetworkTransaction* trans = helper.trans();
5550
5551 TestCompletionCallback callback;
5552 int rv = trans->Start(&request_, callback.callback(), log_);
5553
5554 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5555
5556 data.RunUntilPaused();
5557 base::RunLoop().RunUntilIdle();
5558
5559 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5560 ASSERT_TRUE(stream);
5561 ASSERT_TRUE(stream->stream());
5562 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize) +
5563 kDeltaWindowSize * kDeltaCount -
5564 kMaxSpdyFrameChunkSize * kFrameCount,
5565 stream->stream()->send_window_size());
5566
5567 data.Resume();
5568 base::RunLoop().RunUntilIdle();
5569
5570 rv = callback.WaitForResult();
5571 EXPECT_THAT(rv, IsOk());
5572
5573 helper.VerifyDataConsumed();
5574 }
5575
5576 // Test that received data frames and sent WINDOW_UPDATE frames change
5577 // the recv_window_size_ correctly.
TEST_P(SpdyNetworkTransactionTest,WindowUpdateSent)5578 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5579 // Session level maximum window size that is more than twice the default
5580 // initial window size so that an initial window update is sent.
5581 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
5582 ASSERT_LT(2 * kDefaultInitialWindowSize, session_max_recv_window_size);
5583 // Stream level maximum window size that is less than the session level
5584 // maximum window size so that we test for confusion between the two.
5585 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
5586 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5587 // Size of body to be sent. Has to be less than or equal to both window sizes
5588 // so that we do not run out of receiving window. Also has to be greater than
5589 // half of them so that it triggers both a session level and a stream level
5590 // window update frame.
5591 const int32_t kTargetSize = 3 * 64 * 1024;
5592 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5593 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5594 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5595 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5596 // Size of each DATA frame.
5597 const int32_t kChunkSize = 4096;
5598 // Size of window updates.
5599 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
5600 const int32_t session_window_update_delta =
5601 session_max_recv_window_size / 2 + kChunkSize;
5602 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
5603 const int32_t stream_window_update_delta =
5604 stream_max_recv_window_size / 2 + kChunkSize;
5605
5606 spdy::SpdySerializedFrame preface(
5607 const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
5608 spdy::kHttp2ConnectionHeaderPrefixSize,
5609 /* owns_buffer = */ false);
5610
5611 spdy::SettingsMap initial_settings;
5612 initial_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
5613 initial_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
5614 stream_max_recv_window_size;
5615 initial_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5616 kSpdyMaxHeaderListSize;
5617 initial_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5618 spdy::SpdySerializedFrame initial_settings_frame(
5619 spdy_util_.ConstructSpdySettings(initial_settings));
5620
5621 spdy::SpdySerializedFrame initial_window_update(
5622 spdy_util_.ConstructSpdyWindowUpdate(
5623 spdy::kSessionFlowControlStreamId,
5624 session_max_recv_window_size - kDefaultInitialWindowSize));
5625
5626 spdy::SpdySerializedFrame combined_frames = CombineFrames(
5627 {&preface, &initial_settings_frame, &initial_window_update});
5628
5629 std::vector<MockWrite> writes;
5630 writes.push_back(CreateMockWrite(combined_frames));
5631
5632 spdy::SpdySerializedFrame req(
5633 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5634 writes.push_back(CreateMockWrite(req, writes.size()));
5635
5636 std::vector<MockRead> reads;
5637 spdy::SpdySerializedFrame resp(
5638 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5639 reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
5640
5641 std::vector<spdy::SpdySerializedFrame> body_frames;
5642 const std::string body_data(kChunkSize, 'x');
5643 for (size_t remaining = kTargetSize; remaining != 0;) {
5644 size_t frame_size = std::min(remaining, body_data.size());
5645 body_frames.push_back(spdy_util_.ConstructSpdyDataFrame(
5646 1, base::StringPiece(body_data.data(), frame_size), false));
5647 reads.push_back(
5648 CreateMockRead(body_frames.back(), writes.size() + reads.size()));
5649 remaining -= frame_size;
5650 }
5651 // Yield.
5652 reads.emplace_back(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size());
5653
5654 spdy::SpdySerializedFrame session_window_update(
5655 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
5656 writes.push_back(
5657 CreateMockWrite(session_window_update, writes.size() + reads.size()));
5658 spdy::SpdySerializedFrame stream_window_update(
5659 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
5660 writes.push_back(
5661 CreateMockWrite(stream_window_update, writes.size() + reads.size()));
5662
5663 SequencedSocketData data(reads, writes);
5664
5665 auto session_deps = std::make_unique<SpdySessionDependencies>();
5666 session_deps->session_max_recv_window_size = session_max_recv_window_size;
5667 session_deps->http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
5668 stream_max_recv_window_size;
5669
5670 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
5671 std::move(session_deps));
5672 helper.AddData(&data);
5673 helper.RunPreTestSetup();
5674
5675 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5676 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5677 pool_peer.SetEnableSendingInitialData(true);
5678
5679 HttpNetworkTransaction* trans = helper.trans();
5680 TestCompletionCallback callback;
5681 int rv = trans->Start(&request_, callback.callback(), log_);
5682
5683 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5684 rv = callback.WaitForResult();
5685 EXPECT_THAT(rv, IsOk());
5686
5687 // Finish async network reads.
5688 base::RunLoop().RunUntilIdle();
5689
5690 SpdyHttpStream* stream =
5691 static_cast<SpdyHttpStream*>(trans->stream_.get());
5692 ASSERT_TRUE(stream);
5693 ASSERT_TRUE(stream->stream());
5694
5695 // All data has been read, but not consumed. The window reflects this.
5696 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
5697 stream->stream()->recv_window_size());
5698
5699 const HttpResponseInfo* response = trans->GetResponseInfo();
5700 ASSERT_TRUE(response);
5701 ASSERT_TRUE(response->headers);
5702 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
5703 EXPECT_TRUE(response->was_fetched_via_spdy);
5704
5705 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5706 // size increased to default.
5707 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTargetSize);
5708 EXPECT_EQ(static_cast<int>(kTargetSize),
5709 trans->Read(buf.get(), kTargetSize, CompletionOnceCallback()));
5710 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
5711 stream->stream()->recv_window_size());
5712 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
5713
5714 // Allow scheduled WINDOW_UPDATE frames to write.
5715 base::RunLoop().RunUntilIdle();
5716 helper.VerifyDataConsumed();
5717 }
5718
5719 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
TEST_P(SpdyNetworkTransactionTest,WindowUpdateOverflow)5720 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
5721 // Number of full frames we hope to write (but will not, used to
5722 // set content-length header correctly)
5723 static int kFrameCount = 3;
5724
5725 std::string content(kMaxSpdyFrameChunkSize, 'a');
5726 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
5727 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
5728 0));
5729 spdy::SpdySerializedFrame body(
5730 spdy_util_.ConstructSpdyDataFrame(1, content, false));
5731 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
5732 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
5733
5734 // We're not going to write a data frame with FIN, we'll receive a bad
5735 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5736 MockWrite writes[] = {
5737 CreateMockWrite(req, 0), CreateMockWrite(body, 2),
5738 CreateMockWrite(rst, 3),
5739 };
5740
5741 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
5742 spdy::SpdySerializedFrame window_update(
5743 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5744 MockRead reads[] = {
5745 CreateMockRead(window_update, 1), MockRead(ASYNC, 0, 4) // EOF
5746 };
5747
5748 SequencedSocketData data(reads, writes);
5749
5750 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
5751 for (int i = 0; i < kFrameCount; ++i) {
5752 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
5753 content.data(), content.size()));
5754 }
5755 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
5756
5757 // Setup the request.
5758 request_.method = "POST";
5759 request_.upload_data_stream = &upload_data_stream;
5760
5761 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5762 helper.RunPreTestSetup();
5763 helper.AddData(&data);
5764 HttpNetworkTransaction* trans = helper.trans();
5765
5766 TestCompletionCallback callback;
5767 int rv = trans->Start(&request_, callback.callback(), log_);
5768 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
5769
5770 base::RunLoop().RunUntilIdle();
5771 ASSERT_TRUE(callback.have_result());
5772 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_HTTP2_FLOW_CONTROL_ERROR));
5773 helper.VerifyDataConsumed();
5774 }
5775
5776 // Regression test for https://crbug.com/732019.
5777 // RFC7540 Section 6.9.2: A spdy::SETTINGS_INITIAL_WINDOW_SIZE change that
5778 // causes any stream flow control window to overflow MUST be treated as a
5779 // connection error.
TEST_P(SpdyNetworkTransactionTest,InitialWindowSizeOverflow)5780 TEST_P(SpdyNetworkTransactionTest, InitialWindowSizeOverflow) {
5781 spdy::SpdySerializedFrame window_update(
5782 spdy_util_.ConstructSpdyWindowUpdate(1, 0x60000000));
5783 spdy::SettingsMap settings;
5784 settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 0x60000000;
5785 spdy::SpdySerializedFrame settings_frame(
5786 spdy_util_.ConstructSpdySettings(settings));
5787 MockRead reads[] = {CreateMockRead(window_update, 1),
5788 CreateMockRead(settings_frame, 2)};
5789
5790 spdy::SpdySerializedFrame req(
5791 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5792 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
5793 spdy::SpdySerializedFrame goaway(
5794 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
5795 "New spdy::SETTINGS_INITIAL_WINDOW_SIZE "
5796 "value overflows flow control window of "
5797 "stream 1."));
5798 MockWrite writes[] = {CreateMockWrite(req, 0),
5799 CreateMockWrite(settings_ack, 3),
5800 CreateMockWrite(goaway, 4)};
5801
5802 SequencedSocketData data(reads, writes);
5803 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5804 helper.RunToCompletion(&data);
5805 TransactionHelperResult out = helper.output();
5806 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_FLOW_CONTROL_ERROR));
5807 }
5808
5809 // Tests that we close the connection if we try to enqueue more frames than
5810 // the cap allows.
TEST_P(SpdyNetworkTransactionTest,SessionMaxQueuedCappedFramesExceeded)5811 TEST_P(SpdyNetworkTransactionTest, SessionMaxQueuedCappedFramesExceeded) {
5812 const int kTestSessionMaxQueuedCappedFrames = 5;
5813 const int kTestNumPings = kTestSessionMaxQueuedCappedFrames + 1;
5814 spdy::SettingsMap settings;
5815 settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 0xffff;
5816 spdy::SpdySerializedFrame settings_frame(
5817 spdy_util_.ConstructSpdySettings(settings));
5818 std::vector<spdy::SpdySerializedFrame> ping_frames;
5819
5820 spdy::SpdySerializedFrame req(
5821 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5822 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
5823
5824 std::vector<MockWrite> writes;
5825 std::vector<MockRead> reads;
5826 // Send request, receive SETTINGS and send a SETTINGS ACK.
5827 writes.push_back(CreateMockWrite(req, writes.size() + reads.size()));
5828 reads.push_back(CreateMockRead(settings_frame, writes.size() + reads.size()));
5829 writes.push_back(CreateMockWrite(settings_ack, writes.size() + reads.size()));
5830 // Receive more pings than our limit allows.
5831 for (int i = 1; i <= kTestNumPings; ++i) {
5832 ping_frames.push_back(
5833 spdy_util_.ConstructSpdyPing(/*ping_id=*/i, /*is_ack=*/false));
5834 reads.push_back(
5835 CreateMockRead(ping_frames.back(), writes.size() + reads.size()));
5836 }
5837 // Only write PING ACKs after receiving all of them to ensure they are all in
5838 // the write queue.
5839 for (int i = 1; i <= kTestNumPings; ++i) {
5840 ping_frames.push_back(
5841 spdy_util_.ConstructSpdyPing(/*ping_id=*/i, /*is_ack=*/true));
5842 writes.push_back(
5843 CreateMockWrite(ping_frames.back(), writes.size() + reads.size()));
5844 }
5845 // Stop reading.
5846 reads.emplace_back(ASYNC, 0, writes.size() + reads.size());
5847
5848 SequencedSocketData data(reads, writes);
5849 auto session_deps = std::make_unique<SpdySessionDependencies>();
5850 session_deps->session_max_queued_capped_frames =
5851 kTestSessionMaxQueuedCappedFrames;
5852 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
5853 std::move(session_deps));
5854 helper.RunToCompletion(&data);
5855 TransactionHelperResult out = helper.output();
5856 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_CLOSED));
5857 }
5858
5859 // Test that after hitting a send window size of 0, the write process
5860 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
5861
5862 // This test constructs a POST request followed by enough data frames
5863 // containing 'a' that would make the window size 0, followed by another
5864 // data frame containing default content (which is "hello!") and this frame
5865 // also contains a FIN flag. SequencedSocketData is used to enforce all
5866 // writes, save the last, go through before a read could happen. The last frame
5867 // ("hello!") is not permitted to go through since by the time its turn
5868 // arrives, window size is 0. At this point MessageLoop::Run() called via
5869 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
5870 // which returns after performing all possible writes. We use DCHECKS to
5871 // ensure that last data frame is still there and stream has stalled.
5872 // After that, next read is artifically enforced, which causes a
5873 // WINDOW_UPDATE to be read and I/O process resumes.
TEST_P(SpdyNetworkTransactionTest,FlowControlStallResume)5874 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
5875 const int32_t initial_window_size = kDefaultInitialWindowSize;
5876 // Number of upload data buffers we need to send to zero out the window size
5877 // is the minimal number of upload buffers takes to be bigger than
5878 // |initial_window_size|.
5879 size_t num_upload_buffers =
5880 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5881 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5882 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5883 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5884 size_t num_frames_in_one_upload_buffer =
5885 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
5886
5887 // Construct content for a data frame of maximum size.
5888 std::string content(kMaxSpdyFrameChunkSize, 'a');
5889
5890 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
5891 kDefaultUrl, 1,
5892 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5893 LOWEST, nullptr, 0));
5894
5895 // Full frames.
5896 spdy::SpdySerializedFrame body1(
5897 spdy_util_.ConstructSpdyDataFrame(1, content, false));
5898
5899 // Last frame in each upload data buffer.
5900 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
5901 1,
5902 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
5903 false));
5904
5905 // The very last frame before the stalled frames.
5906 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
5907 1,
5908 base::StringPiece(content.data(), initial_window_size % kBufferSize %
5909 kMaxSpdyFrameChunkSize),
5910 false));
5911
5912 // Data frames to be sent once WINDOW_UPDATE frame is received.
5913
5914 // If kBufferSize * num_upload_buffers > initial_window_size,
5915 // we need one additional frame to send the rest of 'a'.
5916 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5917 'a');
5918 spdy::SpdySerializedFrame body4(
5919 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
5920
5921 // Also send a "hello!" after WINDOW_UPDATE.
5922 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
5923
5924 // Fill in mock writes.
5925 size_t i = 0;
5926 std::vector<MockWrite> writes;
5927 writes.push_back(CreateMockWrite(req, i++));
5928 for (size_t j = 0; j < num_upload_buffers; j++) {
5929 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5930 if (j == num_upload_buffers - 1 &&
5931 (initial_window_size % kBufferSize != 0)) {
5932 writes.push_back(CreateMockWrite(body3, i++));
5933 } else if (k == num_frames_in_one_upload_buffer - 1 &&
5934 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5935 writes.push_back(CreateMockWrite(body2, i++));
5936 } else {
5937 writes.push_back(CreateMockWrite(body1, i++));
5938 }
5939 }
5940 }
5941
5942 // Fill in mock reads.
5943 std::vector<MockRead> reads;
5944 // Force a pause.
5945 reads.emplace_back(ASYNC, ERR_IO_PENDING, i++);
5946 // Construct read frame for window updates that gives enough space to upload
5947 // the rest of the data.
5948 spdy::SpdySerializedFrame session_window_update(
5949 spdy_util_.ConstructSpdyWindowUpdate(0,
5950 kUploadDataSize + last_body.size()));
5951 spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
5952 1, kUploadDataSize + last_body.size()));
5953
5954 reads.push_back(CreateMockRead(session_window_update, i++));
5955 reads.push_back(CreateMockRead(window_update, i++));
5956
5957 // Stalled frames which can be sent after receiving window updates.
5958 if (last_body.size() > 0)
5959 writes.push_back(CreateMockWrite(body4, i++));
5960 writes.push_back(CreateMockWrite(body5, i++));
5961
5962 spdy::SpdySerializedFrame reply(
5963 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
5964 reads.push_back(CreateMockRead(reply, i++));
5965 reads.push_back(CreateMockRead(body2, i++));
5966 reads.push_back(CreateMockRead(body5, i++));
5967 reads.emplace_back(ASYNC, 0, i++); // EOF
5968
5969 SequencedSocketData data(reads, writes);
5970
5971 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
5972 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
5973 upload_data_string.append(kUploadData, kUploadDataSize);
5974 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
5975 upload_data_string.c_str(), upload_data_string.size()));
5976 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
5977
5978 request_.method = "POST";
5979 request_.upload_data_stream = &upload_data_stream;
5980 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5981
5982 helper.AddData(&data);
5983 helper.RunPreTestSetup();
5984
5985 HttpNetworkTransaction* trans = helper.trans();
5986
5987 TestCompletionCallback callback;
5988 int rv = trans->Start(&request_, callback.callback(), log_);
5989 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5990
5991 base::RunLoop().RunUntilIdle(); // Write as much as we can.
5992
5993 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5994 ASSERT_TRUE(stream);
5995 ASSERT_TRUE(stream->stream());
5996 EXPECT_EQ(0, stream->stream()->send_window_size());
5997 if (initial_window_size % kBufferSize != 0) {
5998 // If it does not take whole number of full upload buffer to zero out
5999 // initial window size, then the upload data is not at EOF, because the
6000 // last read must be stalled.
6001 EXPECT_FALSE(upload_data_stream.IsEOF());
6002 } else {
6003 // All the body data should have been read.
6004 // TODO(satorux): This is because of the weirdness in reading the request
6005 // body in OnSendBodyComplete(). See crbug.com/113107.
6006 EXPECT_TRUE(upload_data_stream.IsEOF());
6007 }
6008 // But the body is not yet fully sent (kUploadData is not yet sent)
6009 // since we're send-stalled.
6010 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6011
6012 data.Resume(); // Read in WINDOW_UPDATE frame.
6013 rv = callback.WaitForResult();
6014 EXPECT_THAT(rv, IsOk());
6015
6016 // Finish async network reads.
6017 base::RunLoop().RunUntilIdle();
6018 helper.VerifyDataConsumed();
6019 }
6020
6021 // Test we correctly handle the case where the SETTINGS frame results in
6022 // unstalling the send window.
TEST_P(SpdyNetworkTransactionTest,FlowControlStallResumeAfterSettings)6023 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6024 const int32_t initial_window_size = kDefaultInitialWindowSize;
6025 // Number of upload data buffers we need to send to zero out the window size
6026 // is the minimal number of upload buffers takes to be bigger than
6027 // |initial_window_size|.
6028 size_t num_upload_buffers =
6029 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6030 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6031 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6032 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6033 size_t num_frames_in_one_upload_buffer =
6034 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
6035
6036 // Construct content for a data frame of maximum size.
6037 std::string content(kMaxSpdyFrameChunkSize, 'a');
6038
6039 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
6040 kDefaultUrl, 1,
6041 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
6042 LOWEST, nullptr, 0));
6043
6044 // Full frames.
6045 spdy::SpdySerializedFrame body1(
6046 spdy_util_.ConstructSpdyDataFrame(1, content, false));
6047
6048 // Last frame in each upload data buffer.
6049 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
6050 1,
6051 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
6052 false));
6053
6054 // The very last frame before the stalled frames.
6055 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
6056 1,
6057 base::StringPiece(content.data(), initial_window_size % kBufferSize %
6058 kMaxSpdyFrameChunkSize),
6059 false));
6060
6061 // Data frames to be sent once WINDOW_UPDATE frame is received.
6062
6063 // If kBufferSize * num_upload_buffers > initial_window_size,
6064 // we need one additional frame to send the rest of 'a'.
6065 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6066 'a');
6067 spdy::SpdySerializedFrame body4(
6068 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
6069
6070 // Also send a "hello!" after WINDOW_UPDATE.
6071 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
6072
6073 // Fill in mock writes.
6074 size_t i = 0;
6075 std::vector<MockWrite> writes;
6076 writes.push_back(CreateMockWrite(req, i++));
6077 for (size_t j = 0; j < num_upload_buffers; j++) {
6078 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6079 if (j == num_upload_buffers - 1 &&
6080 (initial_window_size % kBufferSize != 0)) {
6081 writes.push_back(CreateMockWrite(body3, i++));
6082 } else if (k == num_frames_in_one_upload_buffer - 1 &&
6083 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6084 writes.push_back(CreateMockWrite(body2, i++));
6085 } else {
6086 writes.push_back(CreateMockWrite(body1, i++));
6087 }
6088 }
6089 }
6090
6091 // Fill in mock reads.
6092 std::vector<MockRead> reads;
6093 // Force a pause.
6094 reads.emplace_back(ASYNC, ERR_IO_PENDING, i++);
6095
6096 // Construct read frame for SETTINGS that gives enough space to upload the
6097 // rest of the data.
6098 spdy::SettingsMap settings;
6099 settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size * 2;
6100 spdy::SpdySerializedFrame settings_frame_large(
6101 spdy_util_.ConstructSpdySettings(settings));
6102
6103 reads.push_back(CreateMockRead(settings_frame_large, i++));
6104
6105 spdy::SpdySerializedFrame session_window_update(
6106 spdy_util_.ConstructSpdyWindowUpdate(0,
6107 last_body.size() + kUploadDataSize));
6108 reads.push_back(CreateMockRead(session_window_update, i++));
6109
6110 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6111 writes.push_back(CreateMockWrite(settings_ack, i++));
6112
6113 // Stalled frames which can be sent after |settings_ack|.
6114 if (last_body.size() > 0)
6115 writes.push_back(CreateMockWrite(body4, i++));
6116 writes.push_back(CreateMockWrite(body5, i++));
6117
6118 spdy::SpdySerializedFrame reply(
6119 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6120 reads.push_back(CreateMockRead(reply, i++));
6121 reads.push_back(CreateMockRead(body2, i++));
6122 reads.push_back(CreateMockRead(body5, i++));
6123 reads.emplace_back(ASYNC, 0, i++); // EOF
6124
6125 // Force all writes to happen before any read, last write will not
6126 // actually queue a frame, due to window size being 0.
6127 SequencedSocketData data(reads, writes);
6128
6129 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
6130 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
6131 upload_data_string.append(kUploadData, kUploadDataSize);
6132 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
6133 upload_data_string.c_str(), upload_data_string.size()));
6134 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
6135
6136 request_.method = "POST";
6137 request_.upload_data_stream = &upload_data_stream;
6138 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6139
6140 helper.RunPreTestSetup();
6141 helper.AddData(&data);
6142
6143 HttpNetworkTransaction* trans = helper.trans();
6144
6145 TestCompletionCallback callback;
6146 int rv = trans->Start(&request_, callback.callback(), log_);
6147 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6148
6149 data.RunUntilPaused(); // Write as much as we can.
6150 base::RunLoop().RunUntilIdle();
6151
6152 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6153 ASSERT_TRUE(stream);
6154 ASSERT_TRUE(stream->stream());
6155 EXPECT_EQ(0, stream->stream()->send_window_size());
6156
6157 if (initial_window_size % kBufferSize != 0) {
6158 // If it does not take whole number of full upload buffer to zero out
6159 // initial window size, then the upload data is not at EOF, because the
6160 // last read must be stalled.
6161 EXPECT_FALSE(upload_data_stream.IsEOF());
6162 } else {
6163 // All the body data should have been read.
6164 // TODO(satorux): This is because of the weirdness in reading the request
6165 // body in OnSendBodyComplete(). See crbug.com/113107.
6166 EXPECT_TRUE(upload_data_stream.IsEOF());
6167 }
6168 // But the body is not yet fully sent (kUploadData is not yet sent)
6169 // since we're send-stalled.
6170 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6171
6172 // Read in SETTINGS frame to unstall.
6173 data.Resume();
6174 base::RunLoop().RunUntilIdle();
6175
6176 rv = callback.WaitForResult();
6177 helper.VerifyDataConsumed();
6178 // If stream is nullptr, that means it was unstalled and closed.
6179 EXPECT_TRUE(stream->stream() == nullptr);
6180 }
6181
6182 // Test we correctly handle the case where the SETTINGS frame results in a
6183 // negative send window size.
TEST_P(SpdyNetworkTransactionTest,FlowControlNegativeSendWindowSize)6184 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6185 const int32_t initial_window_size = kDefaultInitialWindowSize;
6186 // Number of upload data buffers we need to send to zero out the window size
6187 // is the minimal number of upload buffers takes to be bigger than
6188 // |initial_window_size|.
6189 size_t num_upload_buffers =
6190 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6191 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6192 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6193 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6194 size_t num_frames_in_one_upload_buffer =
6195 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
6196
6197 // Construct content for a data frame of maximum size.
6198 std::string content(kMaxSpdyFrameChunkSize, 'a');
6199
6200 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
6201 kDefaultUrl, 1,
6202 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
6203 LOWEST, nullptr, 0));
6204
6205 // Full frames.
6206 spdy::SpdySerializedFrame body1(
6207 spdy_util_.ConstructSpdyDataFrame(1, content, false));
6208
6209 // Last frame in each upload data buffer.
6210 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
6211 1,
6212 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
6213 false));
6214
6215 // The very last frame before the stalled frames.
6216 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
6217 1,
6218 base::StringPiece(content.data(), initial_window_size % kBufferSize %
6219 kMaxSpdyFrameChunkSize),
6220 false));
6221
6222 // Data frames to be sent once WINDOW_UPDATE frame is received.
6223
6224 // If kBufferSize * num_upload_buffers > initial_window_size,
6225 // we need one additional frame to send the rest of 'a'.
6226 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6227 'a');
6228 spdy::SpdySerializedFrame body4(
6229 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
6230
6231 // Also send a "hello!" after WINDOW_UPDATE.
6232 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
6233
6234 // Fill in mock writes.
6235 size_t i = 0;
6236 std::vector<MockWrite> writes;
6237 writes.push_back(CreateMockWrite(req, i++));
6238 for (size_t j = 0; j < num_upload_buffers; j++) {
6239 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6240 if (j == num_upload_buffers - 1 &&
6241 (initial_window_size % kBufferSize != 0)) {
6242 writes.push_back(CreateMockWrite(body3, i++));
6243 } else if (k == num_frames_in_one_upload_buffer - 1 &&
6244 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6245 writes.push_back(CreateMockWrite(body2, i++));
6246 } else {
6247 writes.push_back(CreateMockWrite(body1, i++));
6248 }
6249 }
6250 }
6251
6252 // Fill in mock reads.
6253 std::vector<MockRead> reads;
6254 // Force a pause.
6255 reads.emplace_back(ASYNC, ERR_IO_PENDING, i++);
6256 // Construct read frame for SETTINGS that makes the send_window_size
6257 // negative.
6258 spdy::SettingsMap new_settings;
6259 new_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size / 2;
6260 spdy::SpdySerializedFrame settings_frame_small(
6261 spdy_util_.ConstructSpdySettings(new_settings));
6262 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6263 // positive.
6264 spdy::SpdySerializedFrame session_window_update_init_size(
6265 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
6266 spdy::SpdySerializedFrame window_update_init_size(
6267 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
6268
6269 reads.push_back(CreateMockRead(settings_frame_small, i++));
6270 reads.push_back(CreateMockRead(session_window_update_init_size, i++));
6271 reads.push_back(CreateMockRead(window_update_init_size, i++));
6272
6273 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6274 writes.push_back(CreateMockWrite(settings_ack, i++));
6275
6276 // Stalled frames which can be sent after |settings_ack|.
6277 if (last_body.size() > 0)
6278 writes.push_back(CreateMockWrite(body4, i++));
6279 writes.push_back(CreateMockWrite(body5, i++));
6280
6281 spdy::SpdySerializedFrame reply(
6282 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6283 reads.push_back(CreateMockRead(reply, i++));
6284 reads.push_back(CreateMockRead(body2, i++));
6285 reads.push_back(CreateMockRead(body5, i++));
6286 reads.emplace_back(ASYNC, 0, i++); // EOF
6287
6288 // Force all writes to happen before any read, last write will not
6289 // actually queue a frame, due to window size being 0.
6290 SequencedSocketData data(reads, writes);
6291
6292 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
6293 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
6294 upload_data_string.append(kUploadData, kUploadDataSize);
6295 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
6296 upload_data_string.c_str(), upload_data_string.size()));
6297 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
6298
6299 request_.method = "POST";
6300 request_.upload_data_stream = &upload_data_stream;
6301 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6302
6303 helper.RunPreTestSetup();
6304 helper.AddData(&data);
6305
6306 HttpNetworkTransaction* trans = helper.trans();
6307
6308 TestCompletionCallback callback;
6309 int rv = trans->Start(&request_, callback.callback(), log_);
6310 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6311
6312 data.RunUntilPaused(); // Write as much as we can.
6313 base::RunLoop().RunUntilIdle();
6314
6315 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6316 ASSERT_TRUE(stream);
6317 ASSERT_TRUE(stream->stream());
6318 EXPECT_EQ(0, stream->stream()->send_window_size());
6319
6320 if (initial_window_size % kBufferSize != 0) {
6321 // If it does not take whole number of full upload buffer to zero out
6322 // initial window size, then the upload data is not at EOF, because the
6323 // last read must be stalled.
6324 EXPECT_FALSE(upload_data_stream.IsEOF());
6325 } else {
6326 // All the body data should have been read.
6327 // TODO(satorux): This is because of the weirdness in reading the request
6328 // body in OnSendBodyComplete(). See crbug.com/113107.
6329 EXPECT_TRUE(upload_data_stream.IsEOF());
6330 }
6331
6332 // Read in WINDOW_UPDATE or SETTINGS frame.
6333 data.Resume();
6334 base::RunLoop().RunUntilIdle();
6335 rv = callback.WaitForResult();
6336 helper.VerifyDataConsumed();
6337 }
6338
TEST_P(SpdyNetworkTransactionTest,ReceivingPushIsConnectionError)6339 TEST_P(SpdyNetworkTransactionTest, ReceivingPushIsConnectionError) {
6340 spdy::Http2HeaderBlock push_headers;
6341 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
6342 spdy::SpdySerializedFrame push(
6343 spdy_util_.ConstructSpdyPushPromise(1, 2, std::move(push_headers)));
6344 MockRead reads[] = {CreateMockRead(push, 1)};
6345
6346 spdy::SpdySerializedFrame req(
6347 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6348 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
6349 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received"));
6350 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
6351
6352 SequencedSocketData data(reads, writes);
6353
6354 auto session_deps = std::make_unique<SpdySessionDependencies>();
6355 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
6356 std::move(session_deps));
6357 helper.RunToCompletion(&data);
6358 TransactionHelperResult out = helper.output();
6359 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
6360 }
6361
6362 // Push streams must have even stream IDs. Test that an incoming push stream
6363 // with odd ID is reset the same way as one with even ID.
TEST_P(SpdyNetworkTransactionTest,ReceivingPushWithOddStreamIdIsConnectionError)6364 TEST_P(SpdyNetworkTransactionTest,
6365 ReceivingPushWithOddStreamIdIsConnectionError) {
6366 spdy::Http2HeaderBlock push_headers;
6367 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
6368 spdy::SpdySerializedFrame push(
6369 spdy_util_.ConstructSpdyPushPromise(1, 3, std::move(push_headers)));
6370 MockRead reads[] = {CreateMockRead(push, 1)};
6371
6372 spdy::SpdySerializedFrame req(
6373 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6374 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
6375 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received"));
6376 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
6377
6378 SequencedSocketData data(reads, writes);
6379
6380 auto session_deps = std::make_unique<SpdySessionDependencies>();
6381 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
6382 std::move(session_deps));
6383 helper.RunToCompletion(&data);
6384 TransactionHelperResult out = helper.output();
6385 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
6386 }
6387
6388 // Regression test for https://crbug.com/493348: request header exceeds 16 kB
6389 // and thus sent in multiple frames when using HTTP/2.
TEST_P(SpdyNetworkTransactionTest,LargeRequest)6390 TEST_P(SpdyNetworkTransactionTest, LargeRequest) {
6391 const std::string kKey("foo");
6392 const std::string kValue(1 << 15, 'z');
6393
6394 request_.extra_headers.SetHeader(kKey, kValue);
6395
6396 spdy::Http2HeaderBlock headers(
6397 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
6398 headers[kKey] = kValue;
6399 spdy::SpdySerializedFrame req(
6400 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
6401 MockWrite writes[] = {
6402 CreateMockWrite(req, 0),
6403 };
6404
6405 spdy::SpdySerializedFrame resp(
6406 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6407 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6408 MockRead reads[] = {
6409 CreateMockRead(resp, 1), CreateMockRead(body, 2),
6410 MockRead(ASYNC, 0, 3) // EOF
6411 };
6412
6413 SequencedSocketData data(reads, writes);
6414 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6415 helper.RunToCompletion(&data);
6416 TransactionHelperResult out = helper.output();
6417
6418 EXPECT_THAT(out.rv, IsOk());
6419 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6420 EXPECT_EQ("hello!", out.response_data);
6421 }
6422
6423 // Regression test for https://crbug.com/535629: response header exceeds 16 kB.
TEST_P(SpdyNetworkTransactionTest,LargeResponseHeader)6424 TEST_P(SpdyNetworkTransactionTest, LargeResponseHeader) {
6425 spdy::Http2HeaderBlock headers(
6426 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
6427 spdy::SpdySerializedFrame req(
6428 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
6429 MockWrite writes[] = {
6430 CreateMockWrite(req, 0),
6431 };
6432
6433 // HPACK decoder implementation limits string literal length to 16 kB.
6434 const char* response_headers[2];
6435 const std::string kKey(16 * 1024, 'a');
6436 response_headers[0] = kKey.data();
6437 const std::string kValue(16 * 1024, 'b');
6438 response_headers[1] = kValue.data();
6439
6440 spdy::SpdySerializedFrame resp(
6441 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
6442 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6443 MockRead reads[] = {
6444 CreateMockRead(resp, 1), CreateMockRead(body, 2),
6445 MockRead(ASYNC, 0, 3) // EOF
6446 };
6447
6448 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6449
6450 SequencedSocketData data(reads, writes);
6451 helper.RunToCompletion(&data);
6452 TransactionHelperResult out = helper.output();
6453
6454 EXPECT_THAT(out.rv, IsOk());
6455 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6456 EXPECT_EQ("hello!", out.response_data);
6457 ASSERT_TRUE(out.response_info.headers->HasHeaderValue(kKey, kValue));
6458 }
6459
6460 // End of line delimiter is forbidden according to RFC 7230 Section 3.2.
TEST_P(SpdyNetworkTransactionTest,CRLFInHeaderValue)6461 TEST_P(SpdyNetworkTransactionTest, CRLFInHeaderValue) {
6462 spdy::SpdySerializedFrame req(
6463 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6464 spdy::SpdySerializedFrame rst(
6465 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
6466 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)};
6467
6468 const char* response_headers[] = {"folded", "foo\r\nbar"};
6469 spdy::SpdySerializedFrame resp(
6470 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
6471 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)};
6472
6473 SequencedSocketData data(reads, writes);
6474
6475 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6476 helper.RunToCompletion(&data);
6477 TransactionHelperResult out = helper.output();
6478
6479 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
6480 }
6481
6482 // Regression test for https://crbug.com/603182.
6483 // No response headers received before RST_STREAM: error.
TEST_P(SpdyNetworkTransactionTest,RstStreamNoError)6484 TEST_P(SpdyNetworkTransactionTest, RstStreamNoError) {
6485 spdy::SpdySerializedFrame req(
6486 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6487 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
6488
6489 spdy::SpdySerializedFrame rst(
6490 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
6491 MockRead reads[] = {CreateMockRead(rst, 1), MockRead(ASYNC, 0, 2)};
6492
6493 SequencedSocketData data(reads, writes);
6494 UseChunkedPostRequest();
6495 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6496 helper.RunToCompletion(&data);
6497 TransactionHelperResult out = helper.output();
6498 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
6499 }
6500
6501 // Regression test for https://crbug.com/603182.
6502 // Response headers and data, then RST_STREAM received,
6503 // before request body is sent: success.
TEST_P(SpdyNetworkTransactionTest,RstStreamNoErrorAfterResponse)6504 TEST_P(SpdyNetworkTransactionTest, RstStreamNoErrorAfterResponse) {
6505 spdy::SpdySerializedFrame req(
6506 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6507 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
6508
6509 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6510 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6511 spdy::SpdySerializedFrame rst(
6512 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
6513 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6514 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
6515
6516 SequencedSocketData data(reads, writes);
6517 UseChunkedPostRequest();
6518 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6519 helper.RunToCompletion(&data);
6520 TransactionHelperResult out = helper.output();
6521 EXPECT_THAT(out.rv, IsOk());
6522 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6523 EXPECT_EQ("hello!", out.response_data);
6524 }
6525
6526 TEST_P(SpdyNetworkTransactionTest, 100Continue) {
6527 spdy::SpdySerializedFrame req(
6528 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6529 MockWrite writes[] = {CreateMockWrite(req, 0)};
6530
6531 spdy::Http2HeaderBlock informational_headers;
6532 informational_headers[spdy::kHttp2StatusHeader] = "100";
6533 spdy::SpdySerializedFrame informational_response(
6534 spdy_util_.ConstructSpdyReply(1, std::move(informational_headers)));
6535 spdy::SpdySerializedFrame resp(
6536 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6537 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6538 MockRead reads[] = {
6539 CreateMockRead(informational_response, 1), CreateMockRead(resp, 2),
6540 CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF
6541 };
6542
6543 SequencedSocketData data(reads, writes);
6544 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6545 helper.RunToCompletion(&data);
6546 TransactionHelperResult out = helper.output();
6547 EXPECT_THAT(out.rv, IsOk());
6548 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6549 EXPECT_EQ("hello!", out.response_data);
6550 }
6551
6552 // "A server can send a complete response prior to the client sending an entire
6553 // request if the response does not depend on any portion of the request that
6554 // has not been sent and received." (RFC7540 Section 8.1)
6555 // Regression test for https://crbug.com/606990. Server responds before POST
6556 // data are sent and closes connection: this must result in
6557 // ERR_CONNECTION_CLOSED (as opposed to ERR_HTTP2_PROTOCOL_ERROR).
TEST_P(SpdyNetworkTransactionTest,ResponseBeforePostDataSent)6558 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostDataSent) {
6559 spdy::SpdySerializedFrame req(
6560 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6561 MockWrite writes[] = {CreateMockWrite(req, 0)};
6562
6563 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6564 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6565 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6566 MockRead(ASYNC, 0, 3)};
6567
6568 SequencedSocketData data(reads, writes);
6569 UseChunkedPostRequest();
6570 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6571
6572 helper.RunPreTestSetup();
6573 helper.AddData(&data);
6574 helper.StartDefaultTest();
6575 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
6576 helper.WaitForCallbackToComplete();
6577 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
6578 }
6579
6580 // Regression test for https://crbug.com/606990.
6581 // Server responds before POST data are sent and resets stream with NO_ERROR.
TEST_P(SpdyNetworkTransactionTest,ResponseAndRstStreamBeforePostDataSent)6582 TEST_P(SpdyNetworkTransactionTest, ResponseAndRstStreamBeforePostDataSent) {
6583 spdy::SpdySerializedFrame req(
6584 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6585 MockWrite writes[] = {CreateMockWrite(req, 0)};
6586
6587 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6588 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6589 spdy::SpdySerializedFrame rst(
6590 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
6591 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6592 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
6593
6594 SequencedSocketData data(reads, writes);
6595 UseChunkedPostRequest();
6596 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6597
6598 helper.RunToCompletion(&data);
6599
6600 TransactionHelperResult out = helper.output();
6601 EXPECT_THAT(out.rv, IsOk());
6602 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6603 EXPECT_EQ("hello!", out.response_data);
6604 }
6605
6606 // Unsupported frames must be ignored. This is especially important for frame
6607 // type 0xb, which used to be the BLOCKED frame in previous versions of SPDY,
6608 // but is going to be used for the ORIGIN frame.
6609 // TODO(bnc): Implement ORIGIN frame support. https://crbug.com/697333
TEST_P(SpdyNetworkTransactionTest,IgnoreUnsupportedOriginFrame)6610 TEST_P(SpdyNetworkTransactionTest, IgnoreUnsupportedOriginFrame) {
6611 spdy::SpdySerializedFrame req(
6612 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6613 MockWrite writes[] = {CreateMockWrite(req, 0)};
6614
6615 const char origin_frame_on_stream_zero[] = {
6616 0x00, 0x00, 0x05, // Length
6617 0x0b, // Type
6618 0x00, // Flags
6619 0x00, 0x00, 0x00, 0x00, // Stream ID
6620 0x00, 0x03, // Origin-Len
6621 'f', 'o', 'o' // ASCII-Origin
6622 };
6623
6624 const char origin_frame_on_stream_one[] = {
6625 0x00, 0x00, 0x05, // Length
6626 0x0b, // Type
6627 0x00, // Flags
6628 0x00, 0x00, 0x00, 0x01, // Stream ID
6629 0x00, 0x03, // Origin-Len
6630 'b', 'a', 'r' // ASCII-Origin
6631 };
6632
6633 spdy::SpdySerializedFrame resp(
6634 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6635 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6636 MockRead reads[] = {MockRead(ASYNC, origin_frame_on_stream_zero,
6637 std::size(origin_frame_on_stream_zero), 1),
6638 CreateMockRead(resp, 2),
6639 MockRead(ASYNC, origin_frame_on_stream_one,
6640 std::size(origin_frame_on_stream_one), 3),
6641 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5)};
6642
6643 SequencedSocketData data(reads, writes);
6644 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6645 helper.RunToCompletion(&data);
6646 TransactionHelperResult out = helper.output();
6647 EXPECT_THAT(out.rv, IsOk());
6648 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6649 EXPECT_EQ("hello!", out.response_data);
6650 }
6651
6652 class SpdyNetworkTransactionTLSUsageCheckTest
6653 : public SpdyNetworkTransactionTest {
6654 protected:
RunTLSUsageCheckTest(std::unique_ptr<SSLSocketDataProvider> ssl_provider)6655 void RunTLSUsageCheckTest(
6656 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
6657 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
6658 0, spdy::ERROR_CODE_INADEQUATE_SECURITY, ""));
6659 MockWrite writes[] = {CreateMockWrite(goaway)};
6660
6661 StaticSocketDataProvider data(base::span<MockRead>(), writes);
6662 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
6663 nullptr);
6664 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
6665 TransactionHelperResult out = helper.output();
6666 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY));
6667 }
6668 };
6669
6670 INSTANTIATE_TEST_SUITE_P(All,
6671 SpdyNetworkTransactionTLSUsageCheckTest,
6672 testing::Values(true, false));
6673
TEST_P(SpdyNetworkTransactionTLSUsageCheckTest,TLSVersionTooOld)6674 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6675 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
6676 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6677 &ssl_provider->ssl_info.connection_status);
6678
6679 RunTLSUsageCheckTest(std::move(ssl_provider));
6680 }
6681
TEST_P(SpdyNetworkTransactionTLSUsageCheckTest,TLSCipherSuiteSucky)6682 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6683 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
6684 // Set to TLS_RSA_WITH_NULL_MD5
6685 SSLConnectionStatusSetCipherSuite(0x1,
6686 &ssl_provider->ssl_info.connection_status);
6687
6688 RunTLSUsageCheckTest(std::move(ssl_provider));
6689 }
6690
6691 // Regression test for https://crbug.com/737143.
6692 // This test sets up an old TLS version just like in TLSVersionTooOld,
6693 // and makes sure that it results in an spdy::ERROR_CODE_INADEQUATE_SECURITY
6694 // even for a non-secure request URL.
TEST_P(SpdyNetworkTransactionTest,InsecureUrlCreatesSecureSpdySession)6695 TEST_P(SpdyNetworkTransactionTest, InsecureUrlCreatesSecureSpdySession) {
6696 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
6697 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6698 &ssl_provider->ssl_info.connection_status);
6699
6700 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
6701 0, spdy::ERROR_CODE_INADEQUATE_SECURITY, ""));
6702 MockWrite writes[] = {CreateMockWrite(goaway)};
6703 StaticSocketDataProvider data(base::span<MockRead>(), writes);
6704
6705 request_.url = GURL("http://www.example.org/");
6706
6707 // Need secure proxy so that insecure URL can use HTTP/2.
6708 auto session_deps = std::make_unique<SpdySessionDependencies>(
6709 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
6710 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
6711 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
6712 std::move(session_deps));
6713
6714 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
6715 TransactionHelperResult out = helper.output();
6716 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY));
6717 }
6718
TEST_P(SpdyNetworkTransactionTest,RequestHeadersCallback)6719 TEST_P(SpdyNetworkTransactionTest, RequestHeadersCallback) {
6720 spdy::SpdySerializedFrame req(
6721 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
6722 MockWrite writes[] = {CreateMockWrite(req, 0)};
6723
6724 spdy::SpdySerializedFrame resp(
6725 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6726 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6727 MockRead reads[] = {
6728 CreateMockRead(resp, 1), CreateMockRead(body, 2),
6729 MockRead(ASYNC, 0, 3) // EOF
6730 };
6731
6732 HttpRawRequestHeaders raw_headers;
6733
6734 SequencedSocketData data(reads, writes);
6735 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6736 helper.RunPreTestSetup();
6737 helper.AddData(&data);
6738 helper.trans()->SetRequestHeadersCallback(base::BindRepeating(
6739 &HttpRawRequestHeaders::Assign, base::Unretained(&raw_headers)));
6740 helper.StartDefaultTest();
6741 helper.FinishDefaultTestWithoutVerification();
6742 EXPECT_FALSE(raw_headers.headers().empty());
6743 std::string value;
6744 EXPECT_TRUE(raw_headers.FindHeaderForTest(":path", &value));
6745 EXPECT_EQ("/", value);
6746 EXPECT_TRUE(raw_headers.FindHeaderForTest(":method", &value));
6747 EXPECT_EQ("GET", value);
6748 EXPECT_TRUE(raw_headers.request_line().empty());
6749 }
6750
6751 #if BUILDFLAG(ENABLE_WEBSOCKETS)
6752
TEST_P(SpdyNetworkTransactionTest,WebSocketOpensNewConnection)6753 TEST_P(SpdyNetworkTransactionTest, WebSocketOpensNewConnection) {
6754 base::HistogramTester histogram_tester;
6755 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6756 helper.RunPreTestSetup();
6757
6758 // First request opens up an HTTP/2 connection.
6759 spdy::SpdySerializedFrame req(
6760 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
6761 MockWrite writes1[] = {CreateMockWrite(req, 0)};
6762
6763 spdy::SpdySerializedFrame resp(
6764 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6765 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6766 MockRead reads1[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6767 MockRead(ASYNC, ERR_IO_PENDING, 3),
6768 MockRead(ASYNC, 0, 4)};
6769
6770 SequencedSocketData data1(reads1, writes1);
6771 helper.AddData(&data1);
6772
6773 // WebSocket request opens a new connection with HTTP/2 disabled.
6774 MockWrite writes2[] = {
6775 MockWrite("GET / HTTP/1.1\r\n"
6776 "Host: www.example.org\r\n"
6777 "Connection: Upgrade\r\n"
6778 "Upgrade: websocket\r\n"
6779 "Origin: http://www.example.org\r\n"
6780 "Sec-WebSocket-Version: 13\r\n"
6781 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
6782 "Sec-WebSocket-Extensions: permessage-deflate; "
6783 "client_max_window_bits\r\n\r\n")};
6784
6785 MockRead reads2[] = {
6786 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
6787 "Upgrade: websocket\r\n"
6788 "Connection: Upgrade\r\n"
6789 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
6790
6791 StaticSocketDataProvider data2(reads2, writes2);
6792
6793 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
6794 // Test that the request has HTTP/2 disabled.
6795 ssl_provider2->next_protos_expected_in_ssl_config = {kProtoHTTP11};
6796 // Force socket to use HTTP/1.1, the default protocol without ALPN.
6797 ssl_provider2->next_proto = kProtoHTTP11;
6798 ssl_provider2->ssl_info.cert =
6799 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
6800 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
6801
6802 TestCompletionCallback callback1;
6803 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
6804 int rv = trans1.Start(&request_, callback1.callback(), log_);
6805 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
6806 rv = callback1.WaitForResult();
6807 ASSERT_THAT(rv, IsOk());
6808
6809 const HttpResponseInfo* response = trans1.GetResponseInfo();
6810 ASSERT_TRUE(response->headers);
6811 EXPECT_TRUE(response->was_fetched_via_spdy);
6812 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6813
6814 std::string response_data;
6815 rv = ReadTransaction(&trans1, &response_data);
6816 EXPECT_THAT(rv, IsOk());
6817 EXPECT_EQ("hello!", response_data);
6818
6819 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
6820 PRIVACY_MODE_DISABLED,
6821 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
6822 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
6823 base::WeakPtr<SpdySession> spdy_session =
6824 helper.session()->spdy_session_pool()->FindAvailableSession(
6825 key, /* enable_ip_based_pooling = */ true,
6826 /* is_websocket = */ false, log_);
6827 ASSERT_TRUE(spdy_session);
6828 EXPECT_FALSE(spdy_session->support_websocket());
6829
6830 HttpRequestInfo request2;
6831 request2.method = "GET";
6832 request2.url = GURL("wss://www.example.org/");
6833 request2.traffic_annotation =
6834 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6835 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
6836 .Equals(HostPortPair::FromURL(request2.url)));
6837 request2.extra_headers.SetHeader("Connection", "Upgrade");
6838 request2.extra_headers.SetHeader("Upgrade", "websocket");
6839 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
6840 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
6841
6842 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
6843
6844 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
6845 trans2.SetWebSocketHandshakeStreamCreateHelper(
6846 &websocket_stream_create_helper);
6847
6848 TestCompletionCallback callback2;
6849 rv = trans2.Start(&request2, callback2.callback(), log_);
6850 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
6851 rv = callback2.WaitForResult();
6852 ASSERT_THAT(rv, IsOk());
6853
6854 // HTTP/2 connection is still open, but WebSocket request did not pool to it.
6855 ASSERT_TRUE(spdy_session);
6856
6857 data1.Resume();
6858 base::RunLoop().RunUntilIdle();
6859 helper.VerifyDataConsumed();
6860
6861 // Server did not advertise WebSocket support.
6862 histogram_tester.ExpectUniqueSample("Net.SpdySession.ServerSupportsWebSocket",
6863 /* support_websocket = false */ 0,
6864 /* expected_count = */ 1);
6865 }
6866
6867 // Make sure that a WebSocket job doesn't pick up a newly created SpdySession
6868 // that doesn't support WebSockets through
6869 // HttpStreamFactory::Job::OnSpdySessionAvailable().
TEST_P(SpdyNetworkTransactionTest,WebSocketDoesUseNewH2SessionWithoutWebSocketSupport)6870 TEST_P(SpdyNetworkTransactionTest,
6871 WebSocketDoesUseNewH2SessionWithoutWebSocketSupport) {
6872 base::HistogramTester histogram_tester;
6873 auto session_deps = std::make_unique<SpdySessionDependencies>();
6874 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
6875 std::move(session_deps));
6876 helper.RunPreTestSetup();
6877
6878 spdy::SpdySerializedFrame req(
6879 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
6880
6881 MockWrite writes[] = {CreateMockWrite(req, 0)};
6882
6883 spdy::SpdySerializedFrame resp1(
6884 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6885 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
6886 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
6887 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
6888
6889 SequencedSocketData data(
6890 // Just as with other operations, this means to pause during connection
6891 // establishment.
6892 MockConnect(ASYNC, ERR_IO_PENDING), reads, writes);
6893 helper.AddData(&data);
6894
6895 MockWrite writes2[] = {
6896 MockWrite(SYNCHRONOUS, 0,
6897 "GET / HTTP/1.1\r\n"
6898 "Host: www.example.org\r\n"
6899 "Connection: Upgrade\r\n"
6900 "Upgrade: websocket\r\n"
6901 "Origin: http://www.example.org\r\n"
6902 "Sec-WebSocket-Version: 13\r\n"
6903 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
6904 "Sec-WebSocket-Extensions: permessage-deflate; "
6905 "client_max_window_bits\r\n\r\n")};
6906
6907 MockRead reads2[] = {
6908 MockRead(SYNCHRONOUS, 1,
6909 "HTTP/1.1 101 Switching Protocols\r\n"
6910 "Upgrade: websocket\r\n"
6911 "Connection: Upgrade\r\n"
6912 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
6913 SequencedSocketData data2(MockConnect(ASYNC, ERR_IO_PENDING), reads2,
6914 writes2);
6915 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
6916 // Test that the request has HTTP/2 disabled.
6917 ssl_provider2->next_protos_expected_in_ssl_config = {kProtoHTTP11};
6918 // Force socket to use HTTP/1.1, the default protocol without ALPN.
6919 ssl_provider2->next_proto = kProtoHTTP11;
6920 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
6921
6922 TestCompletionCallback callback1;
6923 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
6924 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
6925
6926 // Create HTTP/2 connection.
6927 base::RunLoop().RunUntilIdle();
6928
6929 HttpRequestInfo request2;
6930 request2.method = "GET";
6931 request2.url = GURL("wss://www.example.org/");
6932 request2.traffic_annotation =
6933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6934 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
6935 .Equals(HostPortPair::FromURL(request2.url)));
6936 request2.extra_headers.SetHeader("Connection", "Upgrade");
6937 request2.extra_headers.SetHeader("Upgrade", "websocket");
6938 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
6939 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
6940
6941 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
6942
6943 HttpNetworkTransaction trans2(MEDIUM, helper.session());
6944 trans2.SetWebSocketHandshakeStreamCreateHelper(
6945 &websocket_stream_create_helper);
6946
6947 TestCompletionCallback callback2;
6948 rv = trans2.Start(&request2, callback2.callback(), log_);
6949 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
6950
6951 // Run until waiting on both connections.
6952 base::RunLoop().RunUntilIdle();
6953
6954 // The H2 connection completes.
6955 data.socket()->OnConnectComplete(MockConnect(SYNCHRONOUS, OK));
6956 EXPECT_EQ(OK, callback1.WaitForResult());
6957 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
6958 ASSERT_TRUE(response->headers);
6959 EXPECT_TRUE(response->was_fetched_via_spdy);
6960 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6961 std::string response_data;
6962 rv = ReadTransaction(helper.trans(), &response_data);
6963 EXPECT_THAT(rv, IsOk());
6964 EXPECT_EQ("hello!", response_data);
6965
6966 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
6967 PRIVACY_MODE_DISABLED,
6968 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
6969 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
6970
6971 base::WeakPtr<SpdySession> spdy_session =
6972 helper.session()->spdy_session_pool()->FindAvailableSession(
6973 key, /* enable_ip_based_pooling = */ true,
6974 /* is_websocket = */ false, log_);
6975 ASSERT_TRUE(spdy_session);
6976 EXPECT_FALSE(spdy_session->support_websocket());
6977
6978 EXPECT_FALSE(callback2.have_result());
6979
6980 // Create WebSocket stream.
6981 data2.socket()->OnConnectComplete(MockConnect(SYNCHRONOUS, OK));
6982
6983 rv = callback2.WaitForResult();
6984 ASSERT_THAT(rv, IsOk());
6985 helper.VerifyDataConsumed();
6986 }
6987
TEST_P(SpdyNetworkTransactionTest,WebSocketOverHTTP2)6988 TEST_P(SpdyNetworkTransactionTest, WebSocketOverHTTP2) {
6989 base::HistogramTester histogram_tester;
6990 auto session_deps = std::make_unique<SpdySessionDependencies>();
6991 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
6992 std::move(session_deps));
6993 helper.RunPreTestSetup();
6994
6995 spdy::SpdySerializedFrame req(
6996 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
6997 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6998
6999 spdy::Http2HeaderBlock websocket_request_headers;
7000 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7001 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "www.example.org";
7002 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7003 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7004 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7005 websocket_request_headers["origin"] = "http://www.example.org";
7006 websocket_request_headers["sec-websocket-version"] = "13";
7007 websocket_request_headers["sec-websocket-extensions"] =
7008 "permessage-deflate; client_max_window_bits";
7009 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7010 3, std::move(websocket_request_headers), MEDIUM, false));
7011
7012 spdy::SpdySerializedFrame priority1(
7013 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
7014 spdy::SpdySerializedFrame priority2(
7015 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
7016
7017 MockWrite writes[] = {
7018 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 2),
7019 CreateMockWrite(websocket_request, 4), CreateMockWrite(priority1, 5),
7020 CreateMockWrite(priority2, 6)};
7021
7022 spdy::SettingsMap settings;
7023 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7024 spdy::SpdySerializedFrame settings_frame(
7025 spdy_util_.ConstructSpdySettings(settings));
7026 spdy::SpdySerializedFrame resp1(
7027 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7028 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7029 spdy::SpdySerializedFrame websocket_response(
7030 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
7031 MockRead reads[] = {CreateMockRead(settings_frame, 1),
7032 CreateMockRead(resp1, 3), CreateMockRead(body1, 7),
7033 CreateMockRead(websocket_response, 8),
7034 MockRead(ASYNC, 0, 9)};
7035
7036 SequencedSocketData data(reads, writes);
7037 helper.AddData(&data);
7038
7039 TestCompletionCallback callback1;
7040 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
7041 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7042
7043 // Create HTTP/2 connection.
7044 base::RunLoop().RunUntilIdle();
7045
7046 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
7047 PRIVACY_MODE_DISABLED,
7048 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7049 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7050 base::WeakPtr<SpdySession> spdy_session =
7051 helper.session()->spdy_session_pool()->FindAvailableSession(
7052 key, /* enable_ip_based_pooling = */ true,
7053 /* is_websocket = */ true, log_);
7054 ASSERT_TRUE(spdy_session);
7055 EXPECT_TRUE(spdy_session->support_websocket());
7056
7057 HttpRequestInfo request2;
7058 request2.method = "GET";
7059 request2.url = GURL("wss://www.example.org/");
7060 request2.traffic_annotation =
7061 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7062 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7063 .Equals(HostPortPair::FromURL(request2.url)));
7064 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
7065 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7066 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7067 request2.extra_headers.SetHeader("Connection", "Upgrade");
7068 request2.extra_headers.SetHeader("Upgrade", "websocket");
7069
7070 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7071
7072 HttpNetworkTransaction trans2(MEDIUM, helper.session());
7073 trans2.SetWebSocketHandshakeStreamCreateHelper(
7074 &websocket_stream_create_helper);
7075
7076 TestCompletionCallback callback2;
7077 rv = trans2.Start(&request2, callback2.callback(), log_);
7078 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7079
7080 // Create WebSocket stream.
7081 base::RunLoop().RunUntilIdle();
7082 ASSERT_TRUE(spdy_session);
7083
7084 // First request has HIGHEST priority, WebSocket request has MEDIUM priority.
7085 // Changing the priority of the first request to LOWEST changes their order,
7086 // and therefore triggers sending PRIORITY frames.
7087 helper.trans()->SetPriority(LOWEST);
7088
7089 rv = callback1.WaitForResult();
7090 ASSERT_THAT(rv, IsOk());
7091
7092 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
7093 ASSERT_TRUE(response->headers);
7094 EXPECT_TRUE(response->was_fetched_via_spdy);
7095 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7096
7097 std::string response_data;
7098 rv = ReadTransaction(helper.trans(), &response_data);
7099 EXPECT_THAT(rv, IsOk());
7100 EXPECT_EQ("hello!", response_data);
7101
7102 rv = callback2.WaitForResult();
7103 ASSERT_THAT(rv, IsOk());
7104
7105 helper.VerifyDataConsumed();
7106
7107 // Server advertised WebSocket support.
7108 histogram_tester.ExpectUniqueSample("Net.SpdySession.ServerSupportsWebSocket",
7109 /* support_websocket = true */ 1,
7110 /* expected_count = */ 1);
7111 }
7112
7113 // Make sure that a WebSocket job doesn't pick up a newly created SpdySession
7114 // that supports WebSockets through an HTTPS proxy when an H2 server doesn't
7115 // support websockets. See https://crbug.com/1010491.
TEST_P(SpdyNetworkTransactionTest,WebSocketDoesNotUseNewH2SessionWithoutWebSocketSupportOverHttpsProxy)7116 TEST_P(SpdyNetworkTransactionTest,
7117 WebSocketDoesNotUseNewH2SessionWithoutWebSocketSupportOverHttpsProxy) {
7118 auto session_deps = std::make_unique<SpdySessionDependencies>(
7119 ConfiguredProxyResolutionService::CreateFixedForTest(
7120 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
7121
7122 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
7123 std::move(session_deps));
7124 helper.RunPreTestSetup();
7125
7126 spdy::SpdySerializedFrame req(
7127 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
7128
7129 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0,
7130 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7131 "Host: www.example.org:443\r\n"
7132 "Proxy-Connection: keep-alive\r\n\r\n"),
7133 CreateMockWrite(req, 2)};
7134
7135 spdy::SpdySerializedFrame resp1(
7136 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7137 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7138 MockRead reads[] = {MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
7139 CreateMockRead(resp1, 3), CreateMockRead(body1, 4),
7140 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
7141
7142 // SSL data for the proxy.
7143 SSLSocketDataProvider tunnel_ssl_data(ASYNC, OK);
7144 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
7145 &tunnel_ssl_data);
7146
7147 SequencedSocketData data(
7148 // Just as with other operations, this means to pause during connection
7149 // establishment.
7150 MockConnect(ASYNC, ERR_IO_PENDING), reads, writes);
7151 helper.AddData(&data);
7152
7153 MockWrite writes2[] = {
7154 MockWrite(SYNCHRONOUS, 0,
7155 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7156 "Host: www.example.org:443\r\n"
7157 "Proxy-Connection: keep-alive\r\n\r\n"),
7158 MockWrite(SYNCHRONOUS, 2,
7159 "GET / HTTP/1.1\r\n"
7160 "Host: www.example.org\r\n"
7161 "Connection: Upgrade\r\n"
7162 "Upgrade: websocket\r\n"
7163 "Origin: http://www.example.org\r\n"
7164 "Sec-WebSocket-Version: 13\r\n"
7165 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7166 "Sec-WebSocket-Extensions: permessage-deflate; "
7167 "client_max_window_bits\r\n\r\n")};
7168
7169 MockRead reads2[] = {
7170 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
7171 MockRead(SYNCHRONOUS, 3,
7172 "HTTP/1.1 101 Switching Protocols\r\n"
7173 "Upgrade: websocket\r\n"
7174 "Connection: Upgrade\r\n"
7175 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
7176 SequencedSocketData data2(MockConnect(ASYNC, ERR_IO_PENDING), reads2,
7177 writes2);
7178
7179 // SSL data for the proxy.
7180 SSLSocketDataProvider tunnel_ssl_data2(ASYNC, OK);
7181 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
7182 &tunnel_ssl_data2);
7183
7184 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7185 // Test that the request has HTTP/2 disabled.
7186 ssl_provider2->next_protos_expected_in_ssl_config = {kProtoHTTP11};
7187 // Force socket to use HTTP/1.1, the default protocol without ALPN.
7188 ssl_provider2->next_proto = kProtoHTTP11;
7189 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
7190
7191 TestCompletionCallback callback1;
7192 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
7193 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7194
7195 // Create HTTP/2 connection.
7196 base::RunLoop().RunUntilIdle();
7197
7198 HttpRequestInfo request2;
7199 request2.method = "GET";
7200 request2.url = GURL("wss://www.example.org/");
7201 request2.traffic_annotation =
7202 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7203 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7204 .Equals(HostPortPair::FromURL(request2.url)));
7205 request2.extra_headers.SetHeader("Connection", "Upgrade");
7206 request2.extra_headers.SetHeader("Upgrade", "websocket");
7207 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
7208 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7209
7210 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7211
7212 HttpNetworkTransaction trans2(MEDIUM, helper.session());
7213 trans2.SetWebSocketHandshakeStreamCreateHelper(
7214 &websocket_stream_create_helper);
7215
7216 TestCompletionCallback callback2;
7217 rv = trans2.Start(&request2, callback2.callback(), log_);
7218 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7219
7220 // Run until waiting on both connections.
7221 base::RunLoop().RunUntilIdle();
7222
7223 // The H2 connection completes.
7224 data.socket()->OnConnectComplete(MockConnect(SYNCHRONOUS, OK));
7225 EXPECT_EQ(OK, callback1.WaitForResult());
7226 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
7227 ASSERT_TRUE(response->headers);
7228 EXPECT_TRUE(response->was_fetched_via_spdy);
7229 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7230 std::string response_data;
7231 rv = ReadTransaction(helper.trans(), &response_data);
7232 EXPECT_THAT(rv, IsOk());
7233 EXPECT_EQ("hello!", response_data);
7234
7235 SpdySessionKey key(
7236 HostPortPair::FromURL(request_.url),
7237 ProxyUriToProxyChain("https://proxy:70", ProxyServer::SCHEME_HTTPS),
7238 PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
7239 SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7240
7241 base::WeakPtr<SpdySession> spdy_session =
7242 helper.session()->spdy_session_pool()->FindAvailableSession(
7243 key, /* enable_ip_based_pooling = */ true,
7244 /* is_websocket = */ false, log_);
7245 ASSERT_TRUE(spdy_session);
7246 EXPECT_FALSE(spdy_session->support_websocket());
7247
7248 EXPECT_FALSE(callback2.have_result());
7249
7250 // Create WebSocket stream.
7251 data2.socket()->OnConnectComplete(MockConnect(SYNCHRONOUS, OK));
7252
7253 rv = callback2.WaitForResult();
7254 ASSERT_THAT(rv, IsOk());
7255 helper.VerifyDataConsumed();
7256 }
7257
7258 // Same as above, but checks that a WebSocket connection avoids creating a new
7259 // socket if it detects an H2 session when host resolution completes, and
7260 // requests also use different hostnames.
TEST_P(SpdyNetworkTransactionTest,WebSocketOverHTTP2DetectsNewSessionWithAliasing)7261 TEST_P(SpdyNetworkTransactionTest,
7262 WebSocketOverHTTP2DetectsNewSessionWithAliasing) {
7263 base::HistogramTester histogram_tester;
7264 auto session_deps = std::make_unique<SpdySessionDependencies>();
7265 session_deps->host_resolver->set_ondemand_mode(true);
7266 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
7267 std::move(session_deps));
7268 helper.RunPreTestSetup();
7269
7270 spdy::SpdySerializedFrame req(
7271 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
7272 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7273
7274 spdy::Http2HeaderBlock websocket_request_headers;
7275 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7276 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "example.test";
7277 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7278 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7279 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7280 websocket_request_headers["origin"] = "http://example.test";
7281 websocket_request_headers["sec-websocket-version"] = "13";
7282 websocket_request_headers["sec-websocket-extensions"] =
7283 "permessage-deflate; client_max_window_bits";
7284 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7285 3, std::move(websocket_request_headers), MEDIUM, false));
7286
7287 spdy::SpdySerializedFrame priority1(
7288 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
7289 spdy::SpdySerializedFrame priority2(
7290 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
7291
7292 MockWrite writes[] = {
7293 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 2),
7294 CreateMockWrite(websocket_request, 4), CreateMockWrite(priority1, 5),
7295 CreateMockWrite(priority2, 6)};
7296
7297 spdy::SettingsMap settings;
7298 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7299 spdy::SpdySerializedFrame settings_frame(
7300 spdy_util_.ConstructSpdySettings(settings));
7301 spdy::SpdySerializedFrame resp1(
7302 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7303 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7304 spdy::SpdySerializedFrame websocket_response(
7305 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
7306 MockRead reads[] = {CreateMockRead(settings_frame, 1),
7307 CreateMockRead(resp1, 3), CreateMockRead(body1, 7),
7308 CreateMockRead(websocket_response, 8),
7309 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9)};
7310
7311 SequencedSocketData data(reads, writes);
7312 helper.AddData(&data);
7313
7314 TestCompletionCallback callback1;
7315 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
7316 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7317
7318 HttpRequestInfo request2;
7319 request2.method = "GET";
7320 request2.url = GURL("wss://example.test/");
7321 request2.traffic_annotation =
7322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7323 request2.extra_headers.SetHeader("Origin", "http://example.test");
7324 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7325 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7326 request2.extra_headers.SetHeader("Connection", "Upgrade");
7327 request2.extra_headers.SetHeader("Upgrade", "websocket");
7328
7329 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7330
7331 HttpNetworkTransaction trans2(MEDIUM, helper.session());
7332 trans2.SetWebSocketHandshakeStreamCreateHelper(
7333 &websocket_stream_create_helper);
7334
7335 TestCompletionCallback callback2;
7336 rv = trans2.Start(&request2, callback2.callback(), log_);
7337 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7338
7339 // Make sure both requests are blocked on host resolution.
7340 base::RunLoop().RunUntilIdle();
7341
7342 EXPECT_TRUE(helper.session_deps()->host_resolver->has_pending_requests());
7343 // Complete the first DNS lookup, which should result in the first transaction
7344 // creating an H2 session (And completing successfully).
7345 helper.session_deps()->host_resolver->ResolveNow(1);
7346 base::RunLoop().RunUntilIdle();
7347
7348 SpdySessionKey key1(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
7349 PRIVACY_MODE_DISABLED,
7350 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7351 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7352 EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
7353 key1, /* is_websocket = */ false));
7354 base::WeakPtr<SpdySession> spdy_session1 =
7355 helper.session()->spdy_session_pool()->FindAvailableSession(
7356 key1, /* enable_ip_based_pooling = */ true,
7357 /* is_websocket = */ false, log_);
7358 ASSERT_TRUE(spdy_session1);
7359 EXPECT_TRUE(spdy_session1->support_websocket());
7360
7361 // Second DNS lookup completes, which results in creating a WebSocket stream.
7362 helper.session_deps()->host_resolver->ResolveNow(2);
7363 ASSERT_TRUE(spdy_session1);
7364
7365 SpdySessionKey key2(HostPortPair::FromURL(request2.url), ProxyChain::Direct(),
7366 PRIVACY_MODE_DISABLED,
7367 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7368 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7369 EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
7370 key2, /* is_websocket = */ true));
7371 base::WeakPtr<SpdySession> spdy_session2 =
7372 helper.session()->spdy_session_pool()->FindAvailableSession(
7373 key1, /* enable_ip_based_pooling = */ true,
7374 /* is_websocket = */ true, log_);
7375 ASSERT_TRUE(spdy_session2);
7376 EXPECT_EQ(spdy_session1.get(), spdy_session2.get());
7377
7378 base::RunLoop().RunUntilIdle();
7379
7380 // First request has HIGHEST priority, WebSocket request has MEDIUM priority.
7381 // Changing the priority of the first request to LOWEST changes their order,
7382 // and therefore triggers sending PRIORITY frames.
7383 helper.trans()->SetPriority(LOWEST);
7384
7385 rv = callback1.WaitForResult();
7386 ASSERT_THAT(rv, IsOk());
7387
7388 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
7389 ASSERT_TRUE(response->headers);
7390 EXPECT_TRUE(response->was_fetched_via_spdy);
7391 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7392
7393 std::string response_data;
7394 rv = ReadTransaction(helper.trans(), &response_data);
7395 EXPECT_THAT(rv, IsOk());
7396 EXPECT_EQ("hello!", response_data);
7397
7398 rv = callback2.WaitForResult();
7399 ASSERT_THAT(rv, IsOk());
7400
7401 helper.VerifyDataConsumed();
7402 }
7403
7404 // Same as above, but the SpdySession is closed just before use, so the
7405 // WebSocket is sent over a new HTTP/1.x connection instead.
TEST_P(SpdyNetworkTransactionTest,WebSocketOverDetectsNewSessionWithAliasingButClosedBeforeUse)7406 TEST_P(SpdyNetworkTransactionTest,
7407 WebSocketOverDetectsNewSessionWithAliasingButClosedBeforeUse) {
7408 base::HistogramTester histogram_tester;
7409 auto session_deps = std::make_unique<SpdySessionDependencies>();
7410 session_deps->host_resolver->set_ondemand_mode(true);
7411 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
7412 std::move(session_deps));
7413 helper.RunPreTestSetup();
7414
7415 spdy::SpdySerializedFrame req(
7416 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
7417 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7418
7419 MockWrite writes[] = {CreateMockWrite(req, 0),
7420 CreateMockWrite(settings_ack, 2)};
7421
7422 spdy::SettingsMap settings;
7423 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7424 spdy::SpdySerializedFrame settings_frame(
7425 spdy_util_.ConstructSpdySettings(settings));
7426 spdy::SpdySerializedFrame resp1(
7427 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7428 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7429 MockRead reads[] = {CreateMockRead(settings_frame, 1),
7430 CreateMockRead(resp1, 3), CreateMockRead(body1, 4),
7431 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
7432
7433 SequencedSocketData data(reads, writes);
7434 helper.AddData(&data);
7435
7436 MockWrite writes2[] = {
7437 MockWrite("GET / HTTP/1.1\r\n"
7438 "Host: example.test\r\n"
7439 "Connection: Upgrade\r\n"
7440 "Upgrade: websocket\r\n"
7441 "Origin: http://example.test\r\n"
7442 "Sec-WebSocket-Version: 13\r\n"
7443 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7444 "Sec-WebSocket-Extensions: permessage-deflate; "
7445 "client_max_window_bits\r\n\r\n")};
7446 MockRead reads2[] = {
7447 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7448 "Upgrade: websocket\r\n"
7449 "Connection: Upgrade\r\n"
7450 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
7451 StaticSocketDataProvider data2(reads2, writes2);
7452 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7453 // Test that the request has HTTP/2 disabled.
7454 ssl_provider2->next_protos_expected_in_ssl_config = {kProtoHTTP11};
7455 // Force socket to use HTTP/1.1, the default protocol without ALPN.
7456 ssl_provider2->next_proto = kProtoHTTP11;
7457 ssl_provider2->ssl_info.cert =
7458 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
7459 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
7460
7461 TestCompletionCallback callback1;
7462 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
7463 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7464
7465 HttpRequestInfo request2;
7466 request2.method = "GET";
7467 request2.url = GURL("wss://example.test/");
7468 request2.traffic_annotation =
7469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7470 request2.extra_headers.SetHeader("Connection", "Upgrade");
7471 request2.extra_headers.SetHeader("Upgrade", "websocket");
7472 request2.extra_headers.SetHeader("Origin", "http://example.test");
7473 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7474
7475 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7476
7477 HttpNetworkTransaction trans2(MEDIUM, helper.session());
7478 trans2.SetWebSocketHandshakeStreamCreateHelper(
7479 &websocket_stream_create_helper);
7480
7481 TestCompletionCallback callback2;
7482 rv = trans2.Start(&request2, callback2.callback(), log_);
7483 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7484
7485 // Make sure both requests are blocked on host resolution.
7486 base::RunLoop().RunUntilIdle();
7487
7488 EXPECT_TRUE(helper.session_deps()->host_resolver->has_pending_requests());
7489 // Complete the first DNS lookup, which should result in the first transaction
7490 // creating an H2 session (And completing successfully).
7491 helper.session_deps()->host_resolver->ResolveNow(1);
7492
7493 // Complete first request.
7494 rv = callback1.WaitForResult();
7495 ASSERT_THAT(rv, IsOk());
7496 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
7497 ASSERT_TRUE(response->headers);
7498 EXPECT_TRUE(response->was_fetched_via_spdy);
7499 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7500 std::string response_data;
7501 rv = ReadTransaction(helper.trans(), &response_data);
7502 EXPECT_THAT(rv, IsOk());
7503 EXPECT_EQ("hello!", response_data);
7504
7505 SpdySessionKey key1(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
7506 PRIVACY_MODE_DISABLED,
7507 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7508 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7509 base::WeakPtr<SpdySession> spdy_session1 =
7510 helper.session()->spdy_session_pool()->FindAvailableSession(
7511 key1, /* enable_ip_based_pooling = */ true,
7512 /* is_websocket = */ false, log_);
7513 ASSERT_TRUE(spdy_session1);
7514 EXPECT_TRUE(spdy_session1->support_websocket());
7515
7516 // Second DNS lookup completes, which results in creating an alias for the
7517 // SpdySession immediately, and a task is posted asynchronously to use the
7518 // alias..
7519 helper.session_deps()->host_resolver->ResolveNow(2);
7520
7521 SpdySessionKey key2(HostPortPair::FromURL(request2.url), ProxyChain::Direct(),
7522 PRIVACY_MODE_DISABLED,
7523 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7524 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7525 base::WeakPtr<SpdySession> spdy_session2 =
7526 helper.session()->spdy_session_pool()->FindAvailableSession(
7527 key1, /* enable_ip_based_pooling = */ true,
7528 /* is_websocket = */ true, log_);
7529 ASSERT_TRUE(spdy_session2);
7530 EXPECT_EQ(spdy_session1.get(), spdy_session2.get());
7531
7532 // But the session is closed before it can be used.
7533 helper.session()->spdy_session_pool()->CloseAllSessions();
7534
7535 // The second request establishes another connection (without even doing
7536 // another DNS lookup) instead, and uses HTTP/1.x.
7537 rv = callback2.WaitForResult();
7538 ASSERT_THAT(rv, IsOk());
7539
7540 helper.VerifyDataConsumed();
7541 }
7542
TEST_P(SpdyNetworkTransactionTest,WebSocketNegotiatesHttp2)7543 TEST_P(SpdyNetworkTransactionTest, WebSocketNegotiatesHttp2) {
7544 HttpRequestInfo request;
7545 request.method = "GET";
7546 request.url = GURL("wss://www.example.org/");
7547 request.traffic_annotation =
7548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7549 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7550 .Equals(HostPortPair::FromURL(request.url)));
7551 request.extra_headers.SetHeader("Connection", "Upgrade");
7552 request.extra_headers.SetHeader("Upgrade", "websocket");
7553 request.extra_headers.SetHeader("Origin", "http://www.example.org");
7554 request.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7555
7556 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
7557 helper.RunPreTestSetup();
7558
7559 StaticSocketDataProvider data;
7560
7561 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7562 // Test that the request has HTTP/2 disabled.
7563 ssl_provider->next_protos_expected_in_ssl_config = {kProtoHTTP11};
7564 // Force socket to use HTTP/2, which should never happen (TLS implementation
7565 // should fail TLS handshake if server chooses HTTP/2 without client
7566 // advertising support).
7567 ssl_provider->next_proto = kProtoHTTP2;
7568 ssl_provider->ssl_info.cert =
7569 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
7570 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
7571
7572 HttpNetworkTransaction* trans = helper.trans();
7573 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7574 trans->SetWebSocketHandshakeStreamCreateHelper(
7575 &websocket_stream_create_helper);
7576
7577 TestCompletionCallback callback;
7578 int rv = trans->Start(&request, callback.callback(), log_);
7579 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7580 rv = callback.WaitForResult();
7581 ASSERT_THAT(rv, IsError(ERR_NOT_IMPLEMENTED));
7582
7583 helper.VerifyDataConsumed();
7584 }
7585
TEST_P(SpdyNetworkTransactionTest,WebSocketHttp11Required)7586 TEST_P(SpdyNetworkTransactionTest, WebSocketHttp11Required) {
7587 base::HistogramTester histogram_tester;
7588 auto session_deps = std::make_unique<SpdySessionDependencies>();
7589 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
7590 std::move(session_deps));
7591 helper.RunPreTestSetup();
7592
7593 spdy::SpdySerializedFrame req(
7594 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
7595 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7596
7597 spdy::Http2HeaderBlock websocket_request_headers;
7598 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7599 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "www.example.org";
7600 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7601 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7602 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7603 websocket_request_headers["origin"] = "http://www.example.org";
7604 websocket_request_headers["sec-websocket-version"] = "13";
7605 websocket_request_headers["sec-websocket-extensions"] =
7606 "permessage-deflate; client_max_window_bits";
7607 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7608 3, std::move(websocket_request_headers), MEDIUM, false));
7609
7610 spdy::SpdySerializedFrame priority1(
7611 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
7612 spdy::SpdySerializedFrame priority2(
7613 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
7614
7615 MockWrite writes1[] = {CreateMockWrite(req, 0),
7616 CreateMockWrite(settings_ack, 2),
7617 CreateMockWrite(websocket_request, 4)};
7618
7619 spdy::SettingsMap settings;
7620 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7621 spdy::SpdySerializedFrame settings_frame(
7622 spdy_util_.ConstructSpdySettings(settings));
7623 spdy::SpdySerializedFrame resp1(
7624 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7625 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7626 spdy::SpdySerializedFrame websocket_response_http11_required(
7627 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
7628 MockRead reads1[] = {CreateMockRead(settings_frame, 1),
7629 CreateMockRead(resp1, 3),
7630 CreateMockRead(websocket_response_http11_required, 5)};
7631
7632 SequencedSocketData data1(reads1, writes1);
7633 helper.AddData(&data1);
7634
7635 MockWrite writes2[] = {
7636 MockWrite("GET / HTTP/1.1\r\n"
7637 "Host: www.example.org\r\n"
7638 "Connection: Upgrade\r\n"
7639 "Origin: http://www.example.org\r\n"
7640 "Sec-WebSocket-Version: 13\r\n"
7641 "Upgrade: websocket\r\n"
7642 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7643 "Sec-WebSocket-Extensions: permessage-deflate; "
7644 "client_max_window_bits\r\n\r\n")};
7645 MockRead reads2[] = {
7646 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7647 "Upgrade: websocket\r\n"
7648 "Connection: Upgrade\r\n"
7649 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
7650 StaticSocketDataProvider data2(reads2, writes2);
7651 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7652 // Test that the request has HTTP/2 disabled.
7653 ssl_provider2->next_protos_expected_in_ssl_config = {kProtoHTTP11};
7654 // Force socket to use HTTP/1.1, the default protocol without ALPN.
7655 ssl_provider2->next_proto = kProtoHTTP11;
7656 ssl_provider2->ssl_info.cert =
7657 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
7658 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
7659
7660 // Create HTTP/2 connection.
7661 TestCompletionCallback callback1;
7662 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
7663 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7664
7665 // Create HTTP/2 connection.
7666 base::RunLoop().RunUntilIdle();
7667
7668 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyChain::Direct(),
7669 PRIVACY_MODE_DISABLED,
7670 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
7671 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
7672 base::WeakPtr<SpdySession> spdy_session =
7673 helper.session()->spdy_session_pool()->FindAvailableSession(
7674 key, /* enable_ip_based_pooling = */ true,
7675 /* is_websocket = */ true, log_);
7676 ASSERT_TRUE(spdy_session);
7677 EXPECT_TRUE(spdy_session->support_websocket());
7678
7679 HttpRequestInfo request2;
7680 request2.method = "GET";
7681 request2.url = GURL("wss://www.example.org/");
7682 request2.traffic_annotation =
7683 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7684 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7685 .Equals(HostPortPair::FromURL(request2.url)));
7686 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
7687 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7688 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7689 request2.extra_headers.SetHeader("Connection", "Upgrade");
7690 request2.extra_headers.SetHeader("Upgrade", "websocket");
7691
7692 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7693
7694 HttpNetworkTransaction trans2(MEDIUM, helper.session());
7695 trans2.SetWebSocketHandshakeStreamCreateHelper(
7696 &websocket_stream_create_helper);
7697
7698 TestCompletionCallback callback2;
7699 rv = trans2.Start(&request2, callback2.callback(), log_);
7700 EXPECT_THAT(callback2.GetResult(rv), IsOk());
7701
7702 helper.VerifyDataConsumed();
7703
7704 // Server advertised WebSocket support.
7705 histogram_tester.ExpectUniqueSample("Net.SpdySession.ServerSupportsWebSocket",
7706 /* support_websocket = true */ 1,
7707 /* expected_count = */ 1);
7708 }
7709
7710 // When using an HTTP(S) proxy, plaintext WebSockets use CONNECT tunnels. This
7711 // should work for HTTP/2 proxies.
TEST_P(SpdyNetworkTransactionTest,PlaintextWebSocketOverHttp2Proxy)7712 TEST_P(SpdyNetworkTransactionTest, PlaintextWebSocketOverHttp2Proxy) {
7713 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
7714 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7715 HostPortPair("www.example.org", 80)));
7716 const char kWebSocketRequest[] =
7717 "GET / HTTP/1.1\r\n"
7718 "Host: www.example.org\r\n"
7719 "Connection: Upgrade\r\n"
7720 "Upgrade: websocket\r\n"
7721 "Origin: http://www.example.org\r\n"
7722 "Sec-WebSocket-Version: 13\r\n"
7723 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7724 "Sec-WebSocket-Extensions: permessage-deflate; "
7725 "client_max_window_bits\r\n\r\n";
7726 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyDataFrame(
7727 /*stream_id=*/1, kWebSocketRequest, /*fin=*/false));
7728 MockWrite writes[] = {CreateMockWrite(req, 0),
7729 CreateMockWrite(websocket_request, 2)};
7730
7731 spdy::SpdySerializedFrame connect_response(
7732 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7733 const char kWebSocketResponse[] =
7734 "HTTP/1.1 101 Switching Protocols\r\n"
7735 "Upgrade: websocket\r\n"
7736 "Connection: Upgrade\r\n"
7737 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n";
7738 spdy::SpdySerializedFrame websocket_response(
7739 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, kWebSocketResponse,
7740 /*fin=*/false));
7741 MockRead reads[] = {CreateMockRead(connect_response, 1),
7742 CreateMockRead(websocket_response, 3),
7743 MockRead(ASYNC, 0, 4)};
7744
7745 SequencedSocketData data(reads, writes);
7746
7747 request_.url = GURL("ws://www.example.org/");
7748 request_.extra_headers.SetHeader("Connection", "Upgrade");
7749 request_.extra_headers.SetHeader("Upgrade", "websocket");
7750 request_.extra_headers.SetHeader("Origin", "http://www.example.org");
7751 request_.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7752 auto session_deps = std::make_unique<SpdySessionDependencies>(
7753 ConfiguredProxyResolutionService::CreateFixedForTest(
7754 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
7755 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7756 std::move(session_deps));
7757 helper.RunPreTestSetup();
7758 helper.AddData(&data);
7759
7760 HttpNetworkTransaction* trans = helper.trans();
7761 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7762 trans->SetWebSocketHandshakeStreamCreateHelper(
7763 &websocket_stream_create_helper);
7764
7765 EXPECT_TRUE(helper.StartDefaultTest());
7766 helper.WaitForCallbackToComplete();
7767 EXPECT_THAT(helper.output().rv, IsOk());
7768
7769 base::RunLoop().RunUntilIdle();
7770 helper.VerifyDataConsumed();
7771 }
7772
TEST_P(SpdyNetworkTransactionTest,SecureWebSocketOverHttp2Proxy)7773 TEST_P(SpdyNetworkTransactionTest, SecureWebSocketOverHttp2Proxy) {
7774 spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect(
7775 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7776 HostPortPair("www.example.org", 443)));
7777 const char kWebSocketRequest[] =
7778 "GET / HTTP/1.1\r\n"
7779 "Host: www.example.org\r\n"
7780 "Connection: Upgrade\r\n"
7781 "Upgrade: websocket\r\n"
7782 "Origin: http://www.example.org\r\n"
7783 "Sec-WebSocket-Version: 13\r\n"
7784 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7785 "Sec-WebSocket-Extensions: permessage-deflate; "
7786 "client_max_window_bits\r\n\r\n";
7787 spdy::SpdySerializedFrame websocket_request(
7788 spdy_util_.ConstructSpdyDataFrame(1, kWebSocketRequest, false));
7789 MockWrite writes[] = {CreateMockWrite(connect_request, 0),
7790 CreateMockWrite(websocket_request, 2)};
7791
7792 spdy::SpdySerializedFrame connect_response(
7793 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7794 const char kWebSocketResponse[] =
7795 "HTTP/1.1 101 Switching Protocols\r\n"
7796 "Upgrade: websocket\r\n"
7797 "Connection: Upgrade\r\n"
7798 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n";
7799 spdy::SpdySerializedFrame websocket_response(
7800 spdy_util_.ConstructSpdyDataFrame(1, kWebSocketResponse, false));
7801 MockRead reads[] = {CreateMockRead(connect_response, 1),
7802 CreateMockRead(websocket_response, 3),
7803 MockRead(ASYNC, 0, 4)};
7804
7805 SequencedSocketData data(reads, writes);
7806
7807 request_.url = GURL("wss://www.example.org/");
7808 request_.extra_headers.SetHeader("Connection", "Upgrade");
7809 request_.extra_headers.SetHeader("Upgrade", "websocket");
7810 request_.extra_headers.SetHeader("Origin", "http://www.example.org");
7811 request_.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7812 auto session_deps = std::make_unique<SpdySessionDependencies>(
7813 ConfiguredProxyResolutionService::CreateFixedForTest(
7814 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
7815 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7816 std::move(session_deps));
7817 helper.RunPreTestSetup();
7818 helper.AddData(&data);
7819
7820 // Add SSL data for the tunneled connection.
7821 SSLSocketDataProvider ssl_provider(ASYNC, OK);
7822 ssl_provider.ssl_info.cert =
7823 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
7824 // A WebSocket request should not advertise HTTP/2 support.
7825 ssl_provider.next_protos_expected_in_ssl_config = {kProtoHTTP11};
7826 // This test uses WebSocket over HTTP/1.1.
7827 ssl_provider.next_proto = kProtoHTTP11;
7828 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
7829 &ssl_provider);
7830
7831 HttpNetworkTransaction* trans = helper.trans();
7832 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7833 trans->SetWebSocketHandshakeStreamCreateHelper(
7834 &websocket_stream_create_helper);
7835
7836 EXPECT_TRUE(helper.StartDefaultTest());
7837 helper.WaitForCallbackToComplete();
7838 EXPECT_THAT(helper.output().rv, IsOk());
7839 const HttpResponseInfo* response = trans->GetResponseInfo();
7840 ASSERT_TRUE(response);
7841 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
7842 EXPECT_TRUE(response->was_alpn_negotiated);
7843 EXPECT_FALSE(response->was_fetched_via_spdy);
7844 EXPECT_EQ(70, response->remote_endpoint.port());
7845 ASSERT_TRUE(response->headers);
7846 EXPECT_EQ("HTTP/1.1 101 Switching Protocols",
7847 response->headers->GetStatusLine());
7848
7849 base::RunLoop().RunUntilIdle();
7850 helper.VerifyDataConsumed();
7851 }
7852
7853 // Regression test for https://crbug.com/828865.
TEST_P(SpdyNetworkTransactionTest,SecureWebSocketOverHttp2ProxyNegotiatesHttp2)7854 TEST_P(SpdyNetworkTransactionTest,
7855 SecureWebSocketOverHttp2ProxyNegotiatesHttp2) {
7856 spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect(
7857 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7858 HostPortPair("www.example.org", 443)));
7859 MockWrite writes[] = {CreateMockWrite(connect_request, 0)};
7860 spdy::SpdySerializedFrame connect_response(
7861 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7862 MockRead reads[] = {CreateMockRead(connect_response, 1),
7863 MockRead(ASYNC, 0, 2)};
7864 SequencedSocketData data(reads, writes);
7865
7866 request_.url = GURL("wss://www.example.org/");
7867 request_.extra_headers.SetHeader("Connection", "Upgrade");
7868 request_.extra_headers.SetHeader("Upgrade", "websocket");
7869 request_.extra_headers.SetHeader("Origin", "http://www.example.org");
7870 request_.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7871 auto session_deps = std::make_unique<SpdySessionDependencies>(
7872 ConfiguredProxyResolutionService::CreateFixedForTest(
7873 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
7874 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7875 std::move(session_deps));
7876 helper.RunPreTestSetup();
7877 helper.AddData(&data);
7878
7879 // Add SSL data for the tunneled connection.
7880 SSLSocketDataProvider ssl_provider(ASYNC, OK);
7881 ssl_provider.ssl_info.cert =
7882 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
7883 // A WebSocket request should not advertise HTTP/2 support.
7884 ssl_provider.next_protos_expected_in_ssl_config = {kProtoHTTP11};
7885 // The server should not negotiate HTTP/2 over the tunnelled connection,
7886 // but it must be handled gracefully if it does.
7887 ssl_provider.next_proto = kProtoHTTP2;
7888 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
7889 &ssl_provider);
7890
7891 HttpNetworkTransaction* trans = helper.trans();
7892 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7893 trans->SetWebSocketHandshakeStreamCreateHelper(
7894 &websocket_stream_create_helper);
7895
7896 EXPECT_TRUE(helper.StartDefaultTest());
7897 helper.WaitForCallbackToComplete();
7898 EXPECT_THAT(helper.output().rv, IsError(ERR_NOT_IMPLEMENTED));
7899
7900 base::RunLoop().RunUntilIdle();
7901 helper.VerifyDataConsumed();
7902 }
7903
7904 #endif // BUILDFLAG(ENABLE_WEBSOCKETS)
7905
TEST_P(SpdyNetworkTransactionTest,ZeroRTTDoesntConfirm)7906 TEST_P(SpdyNetworkTransactionTest, ZeroRTTDoesntConfirm) {
7907 static const base::TimeDelta kDelay = base::Milliseconds(10);
7908 spdy::SpdySerializedFrame req(
7909 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7910 MockWrite writes[] = {CreateMockWrite(req, 0)};
7911
7912 spdy::SpdySerializedFrame resp(
7913 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7914 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
7915 MockRead reads[] = {
7916 CreateMockRead(resp, 1), CreateMockRead(body, 2),
7917 MockRead(ASYNC, 0, 3) // EOF
7918 };
7919
7920 SequencedSocketData data(reads, writes);
7921 auto session_deps = std::make_unique<SpdySessionDependencies>();
7922 session_deps->enable_early_data = true;
7923 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7924 std::move(session_deps));
7925 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7926 ssl_provider->connect_callback = FastForwardByCallback(kDelay);
7927 // Configure |ssl_provider| to fail if ConfirmHandshake is called. The request
7928 // should still succeed.
7929 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
7930 ssl_provider->confirm_callback = FastForwardByCallback(kDelay);
7931 base::TimeTicks start_time = base::TimeTicks::Now();
7932 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
7933 TransactionHelperResult out = helper.output();
7934 EXPECT_THAT(out.rv, IsOk());
7935 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7936 EXPECT_EQ("hello!", out.response_data);
7937
7938 // The handshake time should include the time it took to run Connect(), but
7939 // not ConfirmHandshake().
7940 LoadTimingInfo load_timing_info;
7941 EXPECT_TRUE(helper.trans()->GetLoadTimingInfo(&load_timing_info));
7942 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
7943 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
7944 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
7945 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
7946 }
7947
7948 // Run multiple concurrent streams that don't require handshake confirmation.
TEST_P(SpdyNetworkTransactionTest,ZeroRTTNoConfirmMultipleStreams)7949 TEST_P(SpdyNetworkTransactionTest, ZeroRTTNoConfirmMultipleStreams) {
7950 spdy::SpdySerializedFrame req1(
7951 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7952 spdy::SpdySerializedFrame req2(
7953 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
7954 MockWrite writes1[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
7955
7956 spdy::SpdySerializedFrame resp1(
7957 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7958 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7959 spdy::SpdySerializedFrame resp2(
7960 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
7961 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
7962 MockRead reads1[] = {
7963 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
7964 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
7965 MockRead(ASYNC, 0, 6) // EOF
7966 };
7967
7968 SequencedSocketData data1(reads1, writes1);
7969 SequencedSocketData data2({}, {});
7970 auto session_deps = std::make_unique<SpdySessionDependencies>();
7971 session_deps->enable_early_data = true;
7972 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7973 std::move(session_deps));
7974 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7975 ssl_provider1->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
7976 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7977 ssl_provider2->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
7978
7979 helper.RunPreTestSetup();
7980 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
7981 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
7982 EXPECT_TRUE(helper.StartDefaultTest());
7983
7984 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
7985 HttpRequestInfo request2;
7986 request2.method = "GET";
7987 request2.url = GURL(kDefaultUrl);
7988 request2.traffic_annotation =
7989 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7990 TestCompletionCallback callback2;
7991 int rv = trans2.Start(&request2, callback2.callback(), log_);
7992 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7993
7994 helper.FinishDefaultTest();
7995 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
7996 helper.VerifyDataConsumed();
7997
7998 TransactionHelperResult out = helper.output();
7999 EXPECT_THAT(out.rv, IsOk());
8000 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8001 EXPECT_EQ("hello!", out.response_data);
8002 }
8003
8004 // Run multiple concurrent streams that require handshake confirmation.
TEST_P(SpdyNetworkTransactionTest,ZeroRTTConfirmMultipleStreams)8005 TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmMultipleStreams) {
8006 spdy::Http2HeaderBlock req_block1(
8007 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8008 spdy::SpdySerializedFrame req1(
8009 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8010 spdy::Http2HeaderBlock req_block2(
8011 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8012 spdy::SpdySerializedFrame req2(
8013 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8014 MockWrite writes[] = {
8015 CreateMockWrite(req1, 0),
8016 CreateMockWrite(req2, 3),
8017 };
8018 spdy::SpdySerializedFrame resp1(
8019 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8020 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8021 spdy::SpdySerializedFrame resp2(
8022 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8023 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8024 MockRead reads[] = {
8025 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8026 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8027 MockRead(ASYNC, 0, 6) // EOF
8028 };
8029
8030 SequencedSocketData data1(reads, writes);
8031 SequencedSocketData data2({}, {});
8032 UsePostRequest();
8033 auto session_deps = std::make_unique<SpdySessionDependencies>();
8034 session_deps->enable_early_data = true;
8035 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8036 std::move(session_deps));
8037 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8038 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8039 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8040 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8041
8042 helper.RunPreTestSetup();
8043 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8044 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8045
8046 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8047 HttpRequestInfo request1;
8048 request1.method = "POST";
8049 request1.url = GURL(kDefaultUrl);
8050 request1.traffic_annotation =
8051 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8052 TestCompletionCallback callback1;
8053 int rv = trans1.Start(&request1, callback1.callback(), log_);
8054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8055
8056 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8057 HttpRequestInfo request2;
8058 request2.method = "POST";
8059 request2.url = GURL(kDefaultUrl);
8060 request2.traffic_annotation =
8061 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8062 TestCompletionCallback callback2;
8063 rv = trans2.Start(&request2, callback2.callback(), log_);
8064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8065
8066 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8067 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8068
8069 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8070 ASSERT_TRUE(response1);
8071 ASSERT_TRUE(response1->headers);
8072 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response1->connection_info);
8073 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8074 std::string response_data;
8075 ReadTransaction(&trans1, &response_data);
8076 EXPECT_EQ("hello!", response_data);
8077
8078 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8079 ASSERT_TRUE(response2);
8080 ASSERT_TRUE(response2->headers);
8081 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
8082 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8083 ReadTransaction(&trans2, &response_data);
8084 EXPECT_EQ("hello!", response_data);
8085
8086 helper.VerifyDataConsumed();
8087 }
8088
8089 // Run multiple concurrent streams, the first require a confirmation and the
8090 // second not requiring confirmation.
TEST_P(SpdyNetworkTransactionTest,ZeroRTTConfirmNoConfirmStreams)8091 TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmNoConfirmStreams) {
8092 // This test orders the writes such that the GET (no confirmation) is written
8093 // before the POST (confirmation required).
8094 spdy::Http2HeaderBlock req_block1(
8095 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8096 spdy::SpdySerializedFrame req1(
8097 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8098 spdy::Http2HeaderBlock req_block2(
8099 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8100 spdy::SpdySerializedFrame req2(
8101 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8102 MockWrite writes[] = {
8103 CreateMockWrite(req1, 0),
8104 CreateMockWrite(req2, 3),
8105 };
8106 spdy::SpdySerializedFrame resp1(
8107 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8108 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8109 spdy::SpdySerializedFrame resp2(
8110 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8111 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8112 MockRead reads[] = {
8113 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8114 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8115 MockRead(ASYNC, 0, 6) // EOF
8116 };
8117
8118 SequencedSocketData data1(reads, writes);
8119 SequencedSocketData data2({}, {});
8120 UsePostRequest();
8121 auto session_deps = std::make_unique<SpdySessionDependencies>();
8122 session_deps->enable_early_data = true;
8123 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8124 std::move(session_deps));
8125 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8126 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8127 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8128 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8129
8130 helper.RunPreTestSetup();
8131 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8132 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8133
8134 // TODO(https://crbug.com/949724): Explicitly verify the ordering of
8135 // ConfirmHandshake and the second stream.
8136
8137 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8138 HttpRequestInfo request1;
8139 request1.method = "POST";
8140 request1.url = GURL(kDefaultUrl);
8141 request1.traffic_annotation =
8142 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8143 TestCompletionCallback callback1;
8144 int rv = trans1.Start(&request1, callback1.callback(), log_);
8145 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8146
8147 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8148 HttpRequestInfo request2;
8149 request2.method = "GET";
8150 request2.url = GURL(kDefaultUrl);
8151 request2.traffic_annotation =
8152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8153 TestCompletionCallback callback2;
8154 rv = trans2.Start(&request2, callback2.callback(), log_);
8155 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8156
8157 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8158 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8159
8160 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8161 ASSERT_TRUE(response1);
8162 ASSERT_TRUE(response1->headers);
8163 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response1->connection_info);
8164 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8165 std::string response_data;
8166 ReadTransaction(&trans1, &response_data);
8167 EXPECT_EQ("hello!", response_data);
8168
8169 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8170 ASSERT_TRUE(response2);
8171 ASSERT_TRUE(response2->headers);
8172 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
8173 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8174 ReadTransaction(&trans2, &response_data);
8175 EXPECT_EQ("hello!", response_data);
8176
8177 helper.VerifyDataConsumed();
8178 }
8179
8180 // Run multiple concurrent streams, the first not requiring confirmation and the
8181 // second requiring confirmation.
TEST_P(SpdyNetworkTransactionTest,ZeroRTTNoConfirmConfirmStreams)8182 TEST_P(SpdyNetworkTransactionTest, ZeroRTTNoConfirmConfirmStreams) {
8183 // This test orders the writes such that the GET (no confirmation) is written
8184 // before the POST (confirmation required).
8185 spdy::Http2HeaderBlock req_block1(
8186 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8187 spdy::SpdySerializedFrame req1(
8188 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8189 spdy::Http2HeaderBlock req_block2(
8190 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8191 spdy::SpdySerializedFrame req2(
8192 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8193 MockWrite writes[] = {
8194 CreateMockWrite(req1, 0),
8195 CreateMockWrite(req2, 3),
8196 };
8197 spdy::SpdySerializedFrame resp1(
8198 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8199 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8200 spdy::SpdySerializedFrame resp2(
8201 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8202 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8203 MockRead reads[] = {
8204 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8205 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8206 MockRead(ASYNC, 0, 6) // EOF
8207 };
8208
8209 SequencedSocketData data1(reads, writes);
8210 SequencedSocketData data2({}, {});
8211 UsePostRequest();
8212 auto session_deps = std::make_unique<SpdySessionDependencies>();
8213 session_deps->enable_early_data = true;
8214 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8215 std::move(session_deps));
8216 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8217 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8218 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8219 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8220
8221 helper.RunPreTestSetup();
8222 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8223 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8224
8225 // TODO(https://crbug.com/949724): Explicitly verify the ordering of
8226 // ConfirmHandshake and the second stream.
8227
8228 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8229 HttpRequestInfo request1;
8230 request1.method = "GET";
8231 request1.url = GURL(kDefaultUrl);
8232 request1.traffic_annotation =
8233 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8234 TestCompletionCallback callback1;
8235 int rv = trans1.Start(&request1, callback1.callback(), log_);
8236 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8237
8238 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8239 HttpRequestInfo request2;
8240 request2.method = "POST";
8241 request2.url = GURL(kDefaultUrl);
8242 request2.traffic_annotation =
8243 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8244 TestCompletionCallback callback2;
8245 rv = trans2.Start(&request2, callback2.callback(), log_);
8246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8247
8248 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8249 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8250
8251 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8252 ASSERT_TRUE(response1);
8253 ASSERT_TRUE(response1->headers);
8254 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response1->connection_info);
8255 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8256 std::string response_data;
8257 ReadTransaction(&trans1, &response_data);
8258 EXPECT_EQ("hello!", response_data);
8259
8260 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8261 ASSERT_TRUE(response2);
8262 ASSERT_TRUE(response2->headers);
8263 EXPECT_EQ(HttpConnectionInfo::kHTTP2, response2->connection_info);
8264 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8265 ReadTransaction(&trans2, &response_data);
8266 EXPECT_EQ("hello!", response_data);
8267
8268 helper.VerifyDataConsumed();
8269 }
8270
TEST_P(SpdyNetworkTransactionTest,ZeroRTTSyncConfirmSyncWrite)8271 TEST_P(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
8272 static const base::TimeDelta kDelay = base::Milliseconds(10);
8273 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8274 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8275 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8276 MockWrite writes[] = {
8277 CreateMockWrite(req, 0, SYNCHRONOUS),
8278 CreateMockWrite(body, 1), // POST upload frame
8279 };
8280
8281 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8282 MockRead reads[] = {
8283 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8284 MockRead(ASYNC, 0, 4) // EOF
8285 };
8286
8287 SequencedSocketData data(reads, writes);
8288 UsePostRequest();
8289 auto session_deps = std::make_unique<SpdySessionDependencies>();
8290 session_deps->enable_early_data = true;
8291 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8292 std::move(session_deps));
8293 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8294 ssl_provider->connect_callback = FastForwardByCallback(kDelay);
8295 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK);
8296 ssl_provider->confirm_callback = FastForwardByCallback(kDelay);
8297 base::TimeTicks start_time = base::TimeTicks::Now();
8298 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8299 TransactionHelperResult out = helper.output();
8300 EXPECT_THAT(out.rv, IsOk());
8301 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8302 EXPECT_EQ("hello!", out.response_data);
8303
8304 // The handshake time should include the time it took to run Connect(), but
8305 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
8306 // assume the connection did not negotiate 0-RTT or the handshake was already
8307 // confirmed.
8308 LoadTimingInfo load_timing_info;
8309 EXPECT_TRUE(helper.trans()->GetLoadTimingInfo(&load_timing_info));
8310 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
8311 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
8312 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
8313 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
8314 }
8315
TEST_P(SpdyNetworkTransactionTest,ZeroRTTSyncConfirmAsyncWrite)8316 TEST_P(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
8317 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8318 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8319 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8320 MockWrite writes[] = {
8321 CreateMockWrite(req, 0, ASYNC),
8322 CreateMockWrite(body, 1), // POST upload frame
8323 };
8324
8325 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8326 MockRead reads[] = {
8327 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8328 MockRead(ASYNC, 0, 4) // EOF
8329 };
8330
8331 SequencedSocketData data(reads, writes);
8332 UsePostRequest();
8333 auto session_deps = std::make_unique<SpdySessionDependencies>();
8334 session_deps->enable_early_data = true;
8335 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8336 std::move(session_deps));
8337 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8338 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK);
8339 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8340 TransactionHelperResult out = helper.output();
8341 EXPECT_THAT(out.rv, IsOk());
8342 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8343 EXPECT_EQ("hello!", out.response_data);
8344 }
8345
TEST_P(SpdyNetworkTransactionTest,ZeroRTTAsyncConfirmSyncWrite)8346 TEST_P(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
8347 static const base::TimeDelta kDelay = base::Milliseconds(10);
8348 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8349 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8350 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8351 MockWrite writes[] = {
8352 CreateMockWrite(req, 0, SYNCHRONOUS),
8353 CreateMockWrite(body, 1), // POST upload frame
8354 };
8355
8356 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8357 MockRead reads[] = {
8358 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8359 MockRead(ASYNC, 0, 4) // EOF
8360 };
8361
8362 SequencedSocketData data(reads, writes);
8363 UsePostRequest();
8364 auto session_deps = std::make_unique<SpdySessionDependencies>();
8365 session_deps->enable_early_data = true;
8366 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8367 std::move(session_deps));
8368 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8369 ssl_provider->connect_callback = FastForwardByCallback(kDelay);
8370 ssl_provider->confirm = MockConfirm(ASYNC, OK);
8371 ssl_provider->confirm_callback = FastForwardByCallback(kDelay);
8372 base::TimeTicks start_time = base::TimeTicks::Now();
8373 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8374 TransactionHelperResult out = helper.output();
8375 EXPECT_THAT(out.rv, IsOk());
8376 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8377 EXPECT_EQ("hello!", out.response_data);
8378
8379 // The handshake time should include the time it took to run Connect() and
8380 // ConfirmHandshake().
8381 LoadTimingInfo load_timing_info;
8382 EXPECT_TRUE(helper.trans()->GetLoadTimingInfo(&load_timing_info));
8383 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
8384 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
8385 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
8386 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
8387 start_time + 2 * kDelay);
8388 }
8389
TEST_P(SpdyNetworkTransactionTest,ZeroRTTAsyncConfirmAsyncWrite)8390 TEST_P(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
8391 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8392 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8393 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8394 MockWrite writes[] = {
8395 CreateMockWrite(req, 0, ASYNC),
8396 CreateMockWrite(body, 1), // POST upload frame
8397 };
8398
8399 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8400 MockRead reads[] = {
8401 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8402 MockRead(ASYNC, 0, 4) // EOF
8403 };
8404
8405 SequencedSocketData data(reads, writes);
8406 UsePostRequest();
8407 auto session_deps = std::make_unique<SpdySessionDependencies>();
8408 session_deps->enable_early_data = true;
8409 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8410 std::move(session_deps));
8411 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8412 ssl_provider->confirm = MockConfirm(ASYNC, OK);
8413 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8414 TransactionHelperResult out = helper.output();
8415 EXPECT_THAT(out.rv, IsOk());
8416 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8417 EXPECT_EQ("hello!", out.response_data);
8418 }
8419
TEST_P(SpdyNetworkTransactionTest,ZeroRTTConfirmErrorSync)8420 TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
8421 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8422 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8423 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8424 MockWrite writes[] = {
8425 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
8426 };
8427
8428 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8429 MockRead reads[] = {
8430 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8431 MockRead(ASYNC, 0, 4) // EOF
8432 };
8433
8434 SequencedSocketData data(reads, writes);
8435 UsePostRequest();
8436 auto session_deps = std::make_unique<SpdySessionDependencies>();
8437 session_deps->enable_early_data = true;
8438 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8439 std::move(session_deps));
8440 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8441 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8442 helper.RunPreTestSetup();
8443 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
8444 helper.RunDefaultTest();
8445 TransactionHelperResult out = helper.output();
8446 EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR));
8447 }
8448
TEST_P(SpdyNetworkTransactionTest,ZeroRTTConfirmErrorAsync)8449 TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
8450 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8451 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8452 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8453 MockWrite writes[] = {
8454 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
8455 };
8456
8457 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8458 MockRead reads[] = {
8459 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8460 MockRead(ASYNC, 0, 4) // EOF
8461 };
8462
8463 SequencedSocketData data(reads, writes);
8464 UsePostRequest();
8465 auto session_deps = std::make_unique<SpdySessionDependencies>();
8466 session_deps->enable_early_data = true;
8467 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8468 std::move(session_deps));
8469 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8470 ssl_provider->confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
8471 helper.RunPreTestSetup();
8472 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
8473 helper.RunDefaultTest();
8474 TransactionHelperResult out = helper.output();
8475 EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR));
8476 }
8477
TEST_P(SpdyNetworkTransactionTest,GreaseSettings)8478 TEST_P(SpdyNetworkTransactionTest, GreaseSettings) {
8479 RecordingNetLogObserver net_log_observer;
8480
8481 auto session_deps = std::make_unique<SpdySessionDependencies>();
8482 session_deps->enable_http2_settings_grease = true;
8483 NormalSpdyTransactionHelper helper(
8484 request_, DEFAULT_PRIORITY,
8485 NetLogWithSource::Make(NetLogSourceType::NONE), std::move(session_deps));
8486
8487 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
8488 SpdySessionPoolPeer pool_peer(spdy_session_pool);
8489 pool_peer.SetEnableSendingInitialData(true);
8490
8491 // Greased setting parameter is random. Hang writes instead of trying to
8492 // construct matching mock data. Extra write and read is needed because mock
8493 // data cannot end on ERR_IO_PENDING. Writes or reads will not actually be
8494 // resumed.
8495 MockWrite writes[] = {MockWrite(ASYNC, ERR_IO_PENDING, 0),
8496 MockWrite(ASYNC, OK, 1)};
8497 MockRead reads[] = {MockRead(ASYNC, ERR_IO_PENDING, 2),
8498 MockRead(ASYNC, OK, 3)};
8499 SequencedSocketData data(reads, writes);
8500 helper.RunPreTestSetup();
8501 helper.AddData(&data);
8502
8503 int rv = helper.trans()->Start(&request_, CompletionOnceCallback{}, log_);
8504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8505
8506 base::RunLoop().RunUntilIdle();
8507
8508 helper.ResetTrans();
8509
8510 EXPECT_FALSE(data.AllReadDataConsumed());
8511 EXPECT_FALSE(data.AllWriteDataConsumed());
8512
8513 const auto entries = net_log_observer.GetEntries();
8514
8515 size_t pos = ExpectLogContainsSomewhere(
8516 entries, 0, NetLogEventType::HTTP2_SESSION_SEND_SETTINGS,
8517 NetLogEventPhase::NONE);
8518 ASSERT_LT(pos, entries.size());
8519
8520 const base::Value::Dict& params = entries[pos].params;
8521 const base::Value::List* const settings = params.FindList("settings");
8522 ASSERT_TRUE(settings);
8523
8524 ASSERT_FALSE(settings->empty());
8525 // Get last setting parameter.
8526 const base::Value& greased_setting = (*settings)[settings->size() - 1];
8527 ASSERT_TRUE(greased_setting.is_string());
8528 base::StringPiece greased_setting_string(greased_setting.GetString());
8529
8530 const std::string kExpectedPrefix = "[id:";
8531 EXPECT_EQ(kExpectedPrefix,
8532 greased_setting_string.substr(0, kExpectedPrefix.size()));
8533 int setting_identifier = 0;
8534 base::StringToInt(greased_setting_string.substr(kExpectedPrefix.size()),
8535 &setting_identifier);
8536 // The setting identifier must be of format 0x?a?a.
8537 EXPECT_EQ(0xa, setting_identifier % 16);
8538 EXPECT_EQ(0xa, (setting_identifier / 256) % 16);
8539 }
8540
8541 // If |http2_end_stream_with_data_frame| is false, then the HEADERS frame of a
8542 // GET request will close the stream using the END_STREAM flag. Test that
8543 // |greased_http2_frame| is ignored and no reserved frames are sent on a closed
8544 // stream.
TEST_P(SpdyNetworkTransactionTest,DoNotGreaseFrameTypeWithGetRequestIfHeadersFrameClosesStream)8545 TEST_P(SpdyNetworkTransactionTest,
8546 DoNotGreaseFrameTypeWithGetRequestIfHeadersFrameClosesStream) {
8547 auto session_deps = std::make_unique<SpdySessionDependencies>();
8548
8549 const uint8_t type = 0x0b;
8550 const uint8_t flags = 0xcc;
8551 const std::string payload("foo");
8552 session_deps->greased_http2_frame =
8553 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8554 {type, flags, payload});
8555 session_deps->http2_end_stream_with_data_frame = false;
8556
8557 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8558 std::move(session_deps));
8559
8560 spdy::SpdySerializedFrame req(
8561 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
8562 MockWrite writes[] = {CreateMockWrite(req, 0)};
8563
8564 spdy::SpdySerializedFrame resp(
8565 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8566 spdy::SpdySerializedFrame response_body(
8567 spdy_util_.ConstructSpdyDataFrame(1, true));
8568
8569 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(response_body, 2),
8570 MockRead(ASYNC, 0, 3)};
8571
8572 SequencedSocketData data(reads, writes);
8573 helper.RunPreTestSetup();
8574 helper.AddData(&data);
8575
8576 TestCompletionCallback callback;
8577 int rv = helper.trans()->Start(&request_, callback.callback(), log_);
8578 EXPECT_THAT(callback.GetResult(rv), IsOk());
8579
8580 base::RunLoop().RunUntilIdle();
8581
8582 helper.VerifyDataConsumed();
8583 }
8584
8585 // Test that if |http2_end_stream_with_data_frame| and |greased_http2_frame| are
8586 // both set, then the HEADERS frame does not have the END_STREAM flag set, it is
8587 // followed by a greased frame, and then by an empty DATA frame with END_STREAM
8588 // set.
TEST_P(SpdyNetworkTransactionTest,GreaseFrameTypeWithGetRequest)8589 TEST_P(SpdyNetworkTransactionTest, GreaseFrameTypeWithGetRequest) {
8590 auto session_deps = std::make_unique<SpdySessionDependencies>();
8591
8592 const uint8_t type = 0x0b;
8593 const uint8_t flags = 0xcc;
8594 const std::string payload("foo");
8595 session_deps->greased_http2_frame =
8596 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8597 {type, flags, payload});
8598 session_deps->http2_end_stream_with_data_frame = true;
8599
8600 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8601 std::move(session_deps));
8602
8603 spdy::Http2HeaderBlock headers(
8604 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8605 spdy::SpdySerializedFrame req(
8606 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), DEFAULT_PRIORITY,
8607 /* fin = */ false));
8608
8609 uint8_t kRawFrameData[] = {
8610 0x00, 0x00, 0x03, // length
8611 0x0b, // type
8612 0xcc, // flags
8613 0x00, 0x00, 0x00, 0x01, // stream ID
8614 'f', 'o', 'o' // payload
8615 };
8616 spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
8617 std::size(kRawFrameData),
8618 /* owns_buffer = */ false);
8619 spdy::SpdySerializedFrame empty_body(
8620 spdy_util_.ConstructSpdyDataFrame(1, "", true));
8621
8622 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1),
8623 CreateMockWrite(empty_body, 2)};
8624
8625 spdy::SpdySerializedFrame resp(
8626 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8627 spdy::SpdySerializedFrame response_body(
8628 spdy_util_.ConstructSpdyDataFrame(1, true));
8629
8630 MockRead reads[] = {CreateMockRead(resp, 3), CreateMockRead(response_body, 4),
8631 MockRead(ASYNC, 0, 5)};
8632
8633 SequencedSocketData data(reads, writes);
8634 helper.RunPreTestSetup();
8635 helper.AddData(&data);
8636
8637 TestCompletionCallback callback;
8638 int rv = helper.trans()->Start(&request_, callback.callback(), log_);
8639 EXPECT_THAT(callback.GetResult(rv), IsOk());
8640
8641 base::RunLoop().RunUntilIdle();
8642
8643 helper.VerifyDataConsumed();
8644 }
8645
8646 // Test sending a greased frame before DATA frame that closes the stream when
8647 // |http2_end_stream_with_data_frame| is false.
TEST_P(SpdyNetworkTransactionTest,GreaseFrameTypeWithPostRequestWhenHeadersFrameClosesStream)8648 TEST_P(SpdyNetworkTransactionTest,
8649 GreaseFrameTypeWithPostRequestWhenHeadersFrameClosesStream) {
8650 UsePostRequest();
8651
8652 auto session_deps = std::make_unique<SpdySessionDependencies>();
8653
8654 const uint8_t type = 0x0b;
8655 const uint8_t flags = 0xcc;
8656 const std::string payload("foo");
8657 session_deps->greased_http2_frame =
8658 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8659 {type, flags, payload});
8660 session_deps->http2_end_stream_with_data_frame = true;
8661
8662 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8663 std::move(session_deps));
8664
8665 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8666 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8667
8668 uint8_t kRawFrameData[] = {
8669 0x00, 0x00, 0x03, // length
8670 0x0b, // type
8671 0xcc, // flags
8672 0x00, 0x00, 0x00, 0x01, // stream ID
8673 'f', 'o', 'o' // payload
8674 };
8675 spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
8676 std::size(kRawFrameData),
8677 /* owns_buffer = */ false);
8678 spdy::SpdySerializedFrame request_body(
8679 spdy_util_.ConstructSpdyDataFrame(1, true));
8680
8681 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1),
8682 CreateMockWrite(request_body, 2)};
8683
8684 spdy::SpdySerializedFrame resp(
8685 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8686 spdy::SpdySerializedFrame response_body(
8687 spdy_util_.ConstructSpdyDataFrame(1, true));
8688
8689 MockRead reads[] = {CreateMockRead(resp, 3), CreateMockRead(response_body, 4),
8690 MockRead(ASYNC, 0, 5)};
8691
8692 SequencedSocketData data(reads, writes);
8693 helper.RunPreTestSetup();
8694 helper.AddData(&data);
8695
8696 TestCompletionCallback callback;
8697 int rv = helper.trans()->Start(&request_, callback.callback(), log_);
8698 EXPECT_THAT(callback.GetResult(rv), IsOk());
8699
8700 base::RunLoop().RunUntilIdle();
8701
8702 helper.VerifyDataConsumed();
8703 }
8704
8705 // Test sending a greased frame before DATA frame that closes the stream.
8706 // |http2_end_stream_with_data_frame| is true but should make no difference,
8707 // because the stream is already closed by a DATA frame.
TEST_P(SpdyNetworkTransactionTest,GreaseFrameTypeWithPostRequestWhenEmptyDataFrameClosesStream)8708 TEST_P(SpdyNetworkTransactionTest,
8709 GreaseFrameTypeWithPostRequestWhenEmptyDataFrameClosesStream) {
8710 UsePostRequest();
8711
8712 auto session_deps = std::make_unique<SpdySessionDependencies>();
8713
8714 const uint8_t type = 0x0b;
8715 const uint8_t flags = 0xcc;
8716 const std::string payload("foo");
8717 session_deps->greased_http2_frame =
8718 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8719 {type, flags, payload});
8720 session_deps->http2_end_stream_with_data_frame = true;
8721
8722 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8723 std::move(session_deps));
8724
8725 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8726 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8727
8728 uint8_t kRawFrameData[] = {
8729 0x00, 0x00, 0x03, // length
8730 0x0b, // type
8731 0xcc, // flags
8732 0x00, 0x00, 0x00, 0x01, // stream ID
8733 'f', 'o', 'o' // payload
8734 };
8735 spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
8736 std::size(kRawFrameData),
8737 /* owns_buffer = */ false);
8738 spdy::SpdySerializedFrame request_body(
8739 spdy_util_.ConstructSpdyDataFrame(1, true));
8740
8741 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1),
8742 CreateMockWrite(request_body, 2)};
8743
8744 spdy::SpdySerializedFrame resp(
8745 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8746 spdy::SpdySerializedFrame response_body(
8747 spdy_util_.ConstructSpdyDataFrame(1, true));
8748
8749 MockRead reads[] = {CreateMockRead(resp, 3), CreateMockRead(response_body, 4),
8750 MockRead(ASYNC, 0, 5)};
8751
8752 SequencedSocketData data(reads, writes);
8753 helper.RunPreTestSetup();
8754 helper.AddData(&data);
8755
8756 TestCompletionCallback callback;
8757 int rv = helper.trans()->Start(&request_, callback.callback(), log_);
8758 EXPECT_THAT(callback.GetResult(rv), IsOk());
8759
8760 base::RunLoop().RunUntilIdle();
8761
8762 helper.VerifyDataConsumed();
8763 }
8764
8765 // According to https://httpwg.org/specs/rfc7540.html#CONNECT, "frame types
8766 // other than DATA or stream management frames (RST_STREAM, WINDOW_UPDATE, and
8767 // PRIORITY) MUST NOT be sent on a connected stream".
8768 // Also test that |http2_end_stream_with_data_frame| has no effect on proxy
8769 // streams.
TEST_P(SpdyNetworkTransactionTest,DoNotGreaseFrameTypeWithConnect)8770 TEST_P(SpdyNetworkTransactionTest, DoNotGreaseFrameTypeWithConnect) {
8771 auto session_deps = std::make_unique<SpdySessionDependencies>(
8772 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
8773 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
8774
8775 const uint8_t type = 0x0b;
8776 const uint8_t flags = 0xcc;
8777 const std::string payload("foo");
8778 session_deps->greased_http2_frame =
8779 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8780 {type, flags, payload});
8781 session_deps->http2_end_stream_with_data_frame = true;
8782
8783 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8784 std::move(session_deps));
8785
8786 // CONNECT to proxy.
8787 spdy::SpdySerializedFrame connect_req(spdy_util_.ConstructSpdyConnect(
8788 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8789 HostPortPair("www.example.org", 443)));
8790 spdy::SpdySerializedFrame connect_response(
8791 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8792
8793 // Tunneled transaction wrapped in DATA frames.
8794 const char req[] =
8795 "GET / HTTP/1.1\r\n"
8796 "Host: www.example.org\r\n"
8797 "Connection: keep-alive\r\n\r\n";
8798 spdy::SpdySerializedFrame tunneled_req(
8799 spdy_util_.ConstructSpdyDataFrame(1, req, false));
8800
8801 const char resp[] =
8802 "HTTP/1.1 200 OK\r\n"
8803 "Content-Length: 5\r\n\r\n"
8804 "hello";
8805 spdy::SpdySerializedFrame tunneled_response(
8806 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
8807
8808 MockWrite writes[] = {CreateMockWrite(connect_req, 0),
8809 CreateMockWrite(tunneled_req, 2)};
8810
8811 MockRead reads[] = {CreateMockRead(connect_response, 1),
8812 CreateMockRead(tunneled_response, 3),
8813 MockRead(ASYNC, 0, 4)};
8814
8815 SequencedSocketData data0(reads, writes);
8816
8817 // HTTP/2 connection to proxy.
8818 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8819 ssl_provider0->next_proto = kProtoHTTP2;
8820 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
8821
8822 // HTTP/1.1 to destination.
8823 SSLSocketDataProvider ssl_provider1(ASYNC, OK);
8824 ssl_provider1.next_proto = kProtoHTTP11;
8825 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
8826 &ssl_provider1);
8827
8828 helper.RunPreTestSetup();
8829 helper.StartDefaultTest();
8830 helper.FinishDefaultTestWithoutVerification();
8831 helper.VerifyDataConsumed();
8832
8833 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
8834 ASSERT_TRUE(response);
8835 ASSERT_TRUE(response->headers);
8836 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8837 EXPECT_FALSE(response->was_fetched_via_spdy);
8838 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1, response->connection_info);
8839 EXPECT_TRUE(response->was_alpn_negotiated);
8840 EXPECT_TRUE(request_.url.SchemeIs("https"));
8841 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
8842 EXPECT_EQ(70, response->remote_endpoint.port());
8843 std::string response_data;
8844 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
8845 EXPECT_EQ("hello", response_data);
8846 }
8847
8848 // Regression test for https://crbug.com/1081955.
8849 // Greasing frame types is enabled, the outgoing HEADERS frame is followed by a
8850 // frame of reserved type, then an empty DATA frame to close the stream.
8851 // Response arrives before reserved frame and DATA frame can be sent.
8852 // SpdyHttpStream::OnDataSent() must not crash.
TEST_P(SpdyNetworkTransactionTest,OnDataSentDoesNotCrashWithGreasedFrameType)8853 TEST_P(SpdyNetworkTransactionTest, OnDataSentDoesNotCrashWithGreasedFrameType) {
8854 auto session_deps = std::make_unique<SpdySessionDependencies>();
8855
8856 const uint8_t type = 0x0b;
8857 const uint8_t flags = 0xcc;
8858 const std::string payload("foo");
8859 session_deps->greased_http2_frame =
8860 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
8861 {type, flags, payload});
8862 session_deps->http2_end_stream_with_data_frame = true;
8863
8864 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8865 std::move(session_deps));
8866
8867 spdy::Http2HeaderBlock headers(
8868 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8869 spdy::SpdySerializedFrame req(
8870 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), DEFAULT_PRIORITY,
8871 /* fin = */ false));
8872
8873 uint8_t kRawFrameData[] = {
8874 0x00, 0x00, 0x03, // length
8875 0x0b, // type
8876 0xcc, // flags
8877 0x00, 0x00, 0x00, 0x01, // stream ID
8878 'f', 'o', 'o' // payload
8879 };
8880 spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
8881 std::size(kRawFrameData),
8882 /* owns_buffer = */ false);
8883 spdy::SpdySerializedFrame empty_body(
8884 spdy_util_.ConstructSpdyDataFrame(1, "", true));
8885
8886 MockWrite writes[] = {
8887 CreateMockWrite(req, 0), MockWrite(ASYNC, ERR_IO_PENDING, 2),
8888 CreateMockWrite(grease, 3), CreateMockWrite(empty_body, 4)};
8889
8890 spdy::SpdySerializedFrame resp(
8891 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8892 spdy::SpdySerializedFrame response_body(
8893 spdy_util_.ConstructSpdyDataFrame(1, true));
8894
8895 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(response_body, 5),
8896 MockRead(ASYNC, 0, 6)};
8897
8898 SequencedSocketData data(reads, writes);
8899 helper.RunPreTestSetup();
8900 helper.AddData(&data);
8901
8902 TestCompletionCallback callback;
8903 int rv = helper.trans()->Start(&request_, callback.callback(), log_);
8904 base::RunLoop().RunUntilIdle();
8905
8906 // Response headers received. Resume sending |grease| and |empty_body|.
8907 data.Resume();
8908 EXPECT_THAT(callback.GetResult(rv), IsOk());
8909
8910 base::RunLoop().RunUntilIdle();
8911
8912 helper.VerifyDataConsumed();
8913 }
8914
TEST_P(SpdyNetworkTransactionTest,NotAllowHTTP1NotBlockH2Post)8915 TEST_P(SpdyNetworkTransactionTest, NotAllowHTTP1NotBlockH2Post) {
8916 spdy::SpdySerializedFrame req(
8917 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
8918 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8919 MockWrite writes[] = {
8920 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
8921 };
8922 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8923 MockRead reads[] = {
8924 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8925 MockRead(ASYNC, 0, 4) // EOF
8926 };
8927 SequencedSocketData data(reads, writes);
8928
8929 request_.method = "POST";
8930 UploadDataStreamNotAllowHTTP1 upload_data(kUploadData);
8931 request_.upload_data_stream = &upload_data;
8932
8933 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
8934 helper.RunToCompletion(&data);
8935 TransactionHelperResult out = helper.output();
8936 EXPECT_THAT(out.rv, IsOk());
8937 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8938 EXPECT_EQ("hello!", out.response_data);
8939 }
8940
TEST_P(SpdyNetworkTransactionTest,AlpsFramingError)8941 TEST_P(SpdyNetworkTransactionTest, AlpsFramingError) {
8942 base::HistogramTester histogram_tester;
8943
8944 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
8945 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "Error parsing ALPS: 3"));
8946 MockWrite writes[] = {CreateMockWrite(goaway, 0)};
8947 SequencedSocketData data(base::span<MockRead>(), writes);
8948
8949 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8950 // Not a complete HTTP/2 frame.
8951 ssl_provider->peer_application_settings = "boo";
8952
8953 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
8954 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8955
8956 TransactionHelperResult out = helper.output();
8957 EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
8958
8959 histogram_tester.ExpectUniqueSample(
8960 "Net.SpdySession.AlpsDecoderStatus",
8961 static_cast<int>(AlpsDecoder::Error::kNotOnFrameBoundary), 1);
8962 histogram_tester.ExpectTotalCount("Net.SpdySession.AlpsAcceptChEntries", 0);
8963 histogram_tester.ExpectTotalCount("Net.SpdySession.AlpsSettingParameterCount",
8964 0);
8965 }
8966
8967 } // namespace net
8968