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