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