OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/test_tools/quic_test_client.h" | 5 #include "net/tools/quic/test_tools/quic_test_client.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
13 #include "net/base/completion_callback.h" | 13 #include "net/base/completion_callback.h" |
14 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
15 #include "net/cert/cert_verify_result.h" | 15 #include "net/cert/cert_verify_result.h" |
16 #include "net/cert/x509_certificate.h" | 16 #include "net/cert/x509_certificate.h" |
17 #include "net/quic/core/crypto/proof_verifier.h" | 17 #include "net/quic/core/crypto/proof_verifier.h" |
18 #include "net/quic/core/quic_flags.h" | 18 #include "net/quic/core/quic_flags.h" |
19 #include "net/quic/core/quic_server_id.h" | 19 #include "net/quic/core/quic_server_id.h" |
20 #include "net/quic/core/quic_utils.h" | 20 #include "net/quic/core/quic_utils.h" |
| 21 #include "net/quic/core/spdy_utils.h" |
21 #include "net/quic/test_tools/crypto_test_utils.h" | 22 #include "net/quic/test_tools/crypto_test_utils.h" |
22 #include "net/quic/test_tools/quic_connection_peer.h" | 23 #include "net/quic/test_tools/quic_connection_peer.h" |
23 #include "net/quic/test_tools/quic_spdy_session_peer.h" | 24 #include "net/quic/test_tools/quic_spdy_session_peer.h" |
24 #include "net/quic/test_tools/quic_test_utils.h" | 25 #include "net/quic/test_tools/quic_test_utils.h" |
25 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | 26 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
26 #include "net/tools/balsa/balsa_headers.h" | |
27 #include "net/tools/quic/quic_epoll_connection_helper.h" | 27 #include "net/tools/quic/quic_epoll_connection_helper.h" |
28 #include "net/tools/quic/quic_packet_writer_wrapper.h" | 28 #include "net/tools/quic/quic_packet_writer_wrapper.h" |
29 #include "net/tools/quic/quic_spdy_client_stream.h" | 29 #include "net/tools/quic/quic_spdy_client_stream.h" |
30 #include "net/tools/quic/spdy_balsa_utils.h" | 30 #include "net/tools/quic/spdy_balsa_utils.h" |
31 #include "net/tools/quic/test_tools/http_message.h" | 31 #include "net/tools/quic/test_tools/http_message.h" |
32 #include "net/tools/quic/test_tools/quic_client_peer.h" | 32 #include "net/tools/quic/test_tools/quic_client_peer.h" |
33 #include "url/gurl.h" | 33 #include "url/gurl.h" |
34 | 34 |
35 using base::StringPiece; | 35 using base::StringPiece; |
36 using net::QuicServerId; | 36 using net::QuicServerId; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 const string& cert_sct() const { return cert_sct_; } | 113 const string& cert_sct() const { return cert_sct_; } |
114 | 114 |
115 private: | 115 private: |
116 std::unique_ptr<ProofVerifier> verifier_; | 116 std::unique_ptr<ProofVerifier> verifier_; |
117 string common_name_; | 117 string common_name_; |
118 string cert_sct_; | 118 string cert_sct_; |
119 }; | 119 }; |
120 | 120 |
121 } // anonymous namespace | 121 } // anonymous namespace |
122 | 122 |
123 BalsaHeaders* MungeHeaders(const BalsaHeaders* const_headers) { | |
124 StringPiece uri = const_headers->request_uri(); | |
125 if (uri.empty()) { | |
126 return nullptr; | |
127 } | |
128 if (const_headers->request_method() == "CONNECT") { | |
129 return nullptr; | |
130 } | |
131 BalsaHeaders* headers = new BalsaHeaders; | |
132 headers->CopyFrom(*const_headers); | |
133 if (!base::StartsWith(uri, "https://", | |
134 base::CompareCase::INSENSITIVE_ASCII) && | |
135 !base::StartsWith(uri, "http://", base::CompareCase::INSENSITIVE_ASCII)) { | |
136 // If we have a relative URL, set some defaults. | |
137 string full_uri = "https://test.example.com"; | |
138 full_uri.append(uri.as_string()); | |
139 headers->SetRequestUri(full_uri); | |
140 } | |
141 return headers; | |
142 } | |
143 | |
144 MockableQuicClient::MockableQuicClient( | 123 MockableQuicClient::MockableQuicClient( |
145 IPEndPoint server_address, | 124 IPEndPoint server_address, |
146 const QuicServerId& server_id, | 125 const QuicServerId& server_id, |
147 const QuicVersionVector& supported_versions, | 126 const QuicVersionVector& supported_versions, |
148 EpollServer* epoll_server) | 127 EpollServer* epoll_server) |
149 : MockableQuicClient(server_address, | 128 : MockableQuicClient(server_address, |
150 server_id, | 129 server_id, |
151 QuicConfig(), | 130 QuicConfig(), |
152 supported_versions, | 131 supported_versions, |
153 epoll_server) {} | 132 epoll_server) {} |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 if (!client_->config()->HasSetBytesForConnectionIdToSend()) { | 265 if (!client_->config()->HasSetBytesForConnectionIdToSend()) { |
287 client_->config()->SetBytesForConnectionIdToSend(0); | 266 client_->config()->SetBytesForConnectionIdToSend(0); |
288 } | 267 } |
289 } | 268 } |
290 | 269 |
291 void QuicTestClient::SetUserAgentID(const string& user_agent_id) { | 270 void QuicTestClient::SetUserAgentID(const string& user_agent_id) { |
292 client_->SetUserAgentID(user_agent_id); | 271 client_->SetUserAgentID(user_agent_id); |
293 } | 272 } |
294 | 273 |
295 ssize_t QuicTestClient::SendRequest(const string& uri) { | 274 ssize_t QuicTestClient::SendRequest(const string& uri) { |
296 HTTPMessage message; | 275 SpdyHeaderBlock headers; |
297 FillInRequest(uri, &message); | 276 if (!PopulateHeaderBlockFromUrl(uri, &headers)) { |
298 return SendMessage(message); | 277 return 0; |
| 278 } |
| 279 return SendMessage(headers, ""); |
299 } | 280 } |
300 | 281 |
301 void QuicTestClient::SendRequestsAndWaitForResponses( | 282 void QuicTestClient::SendRequestsAndWaitForResponses( |
302 const std::vector<string>& url_list) { | 283 const std::vector<string>& url_list) { |
303 for (const string& url : url_list) { | 284 for (const string& url : url_list) { |
304 SendRequest(url); | 285 SendRequest(url); |
305 } | 286 } |
306 while (client()->WaitForEvents()) { | 287 while (client()->WaitForEvents()) { |
307 } | 288 } |
308 return; | 289 return; |
309 } | 290 } |
310 | 291 |
311 ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest( | 292 ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest( |
312 const BalsaHeaders* headers, | 293 const SpdyHeaderBlock* headers, |
313 StringPiece body, | 294 StringPiece body, |
314 bool fin, | 295 bool fin, |
315 QuicAckListenerInterface* delegate) { | 296 QuicAckListenerInterface* delegate) { |
316 if (headers) { | 297 if (headers) { |
317 QuicClientPushPromiseIndex::TryHandle* handle; | 298 QuicClientPushPromiseIndex::TryHandle* handle; |
318 QuicAsyncStatus rv = client()->push_promise_index()->Try( | 299 QuicAsyncStatus rv = |
319 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers), this, &handle); | 300 client()->push_promise_index()->Try(*headers, this, &handle); |
320 if (rv == QUIC_SUCCESS) | 301 if (rv == QUIC_SUCCESS) |
321 return 1; | 302 return 1; |
322 if (rv == QUIC_PENDING) { | 303 if (rv == QUIC_PENDING) { |
323 // May need to retry request if asynchronous rendezvous fails. | 304 // May need to retry request if asynchronous rendezvous fails. |
324 std::unique_ptr<SpdyHeaderBlock> new_headers(new SpdyHeaderBlock( | 305 std::unique_ptr<SpdyHeaderBlock> new_headers( |
325 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers))); | 306 new SpdyHeaderBlock(headers->Clone())); |
326 push_promise_data_to_resend_.reset(new TestClientDataToResend( | 307 push_promise_data_to_resend_.reset(new TestClientDataToResend( |
327 std::move(new_headers), body, fin, this, delegate)); | 308 std::move(new_headers), body, fin, this, delegate)); |
328 return 1; | 309 return 1; |
329 } | 310 } |
330 } | 311 } |
331 | 312 |
332 // Maybe it's better just to overload this. it's just that we need | 313 // Maybe it's better just to overload this. it's just that we need |
333 // for the GetOrCreateStream function to call something else...which | 314 // for the GetOrCreateStream function to call something else...which |
334 // is icky and complicated, but maybe not worse than this. | 315 // is icky and complicated, but maybe not worse than this. |
335 QuicSpdyClientStream* stream = GetOrCreateStream(); | 316 QuicSpdyClientStream* stream = GetOrCreateStream(); |
336 if (stream == nullptr) { | 317 if (stream == nullptr) { |
337 return 0; | 318 return 0; |
338 } | 319 } |
339 | 320 |
340 ssize_t ret = 0; | 321 ssize_t ret = 0; |
341 if (headers != nullptr) { | 322 if (headers != nullptr) { |
342 SpdyHeaderBlock spdy_headers = | 323 SpdyHeaderBlock spdy_headers(headers->Clone()); |
343 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers); | 324 if (spdy_headers[":authority"].as_string().empty()) { |
344 if (headers->HasHeader("transfer-encoding")) { | |
345 // We have tests which rely on sending a non-standards-compliant | |
346 // T-E header. | |
347 string encoding; | |
348 headers->GetAllOfHeaderAsString("transfer-encoding", &encoding); | |
349 spdy_headers.insert(std::make_pair("transfer-encoding", encoding)); | |
350 } | |
351 auto authority = spdy_headers.find(":authority"); | |
352 if (authority == spdy_headers.end() || authority->second.empty()) { | |
353 // HTTP/2 requests should include the :authority pseudo hader. | |
354 spdy_headers[":authority"] = client_->server_id().host(); | 325 spdy_headers[":authority"] = client_->server_id().host(); |
355 } | 326 } |
356 ret = stream->SendRequest(std::move(spdy_headers), body, fin); | 327 ret = stream->SendRequest(std::move(spdy_headers), body, fin); |
357 ++num_requests_; | 328 ++num_requests_; |
358 } else { | 329 } else { |
359 stream->WriteOrBufferBody(body.as_string(), fin, delegate); | 330 stream->WriteOrBufferBody(body.as_string(), fin, delegate); |
360 ret = body.length(); | 331 ret = body.length(); |
361 } | 332 } |
362 if (FLAGS_enable_quic_stateless_reject_support) { | 333 if (FLAGS_enable_quic_stateless_reject_support) { |
363 std::unique_ptr<SpdyHeaderBlock> new_headers; | 334 std::unique_ptr<SpdyHeaderBlock> new_headers; |
364 if (headers) { | 335 if (headers) { |
365 new_headers.reset(new SpdyHeaderBlock( | 336 new_headers.reset(new SpdyHeaderBlock(headers->Clone())); |
366 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers))); | |
367 } | 337 } |
368 std::unique_ptr<QuicClientBase::QuicDataToResend> data_to_resend( | 338 std::unique_ptr<QuicClientBase::QuicDataToResend> data_to_resend( |
369 new TestClientDataToResend(std::move(new_headers), body, fin, this, | 339 new TestClientDataToResend(std::move(new_headers), body, fin, this, |
370 delegate)); | 340 delegate)); |
371 client()->MaybeAddQuicDataToResend(std::move(data_to_resend)); | 341 client()->MaybeAddQuicDataToResend(std::move(data_to_resend)); |
372 } | 342 } |
373 return ret; | 343 return ret; |
374 } | 344 } |
375 | 345 |
376 ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) { | 346 ssize_t QuicTestClient::SendMessage(const SpdyHeaderBlock& headers, |
| 347 StringPiece body) { |
| 348 return SendMessage(headers, body, /*fin=*/true); |
| 349 } |
| 350 |
| 351 ssize_t QuicTestClient::SendMessage(const SpdyHeaderBlock& headers, |
| 352 StringPiece body, |
| 353 bool fin) { |
377 stream_ = nullptr; // Always force creation of a stream for SendMessage. | 354 stream_ = nullptr; // Always force creation of a stream for SendMessage. |
378 // Any response we might have received for a previous request would no longer | 355 // Any response we might have received for a previous request would no longer |
379 // be valid. TODO(jeffpiazza): There's probably additional client state that | 356 // be valid. TODO(jeffpiazza): There's probably additional client state that |
380 // should be reset here, too, if we were being more careful. | 357 // should be reset here, too, if we were being more careful. |
381 response_complete_ = false; | 358 response_complete_ = false; |
382 | 359 |
383 // If we're not connected, try to find an sni hostname. | 360 // If we're not connected, try to find an sni hostname. |
384 if (!connected()) { | 361 if (!connected()) { |
385 GURL url(message.headers()->request_uri()); | 362 GURL url(SpdyUtils::GetUrlFromHeaderBlock(headers)); |
386 if (override_sni_set_) { | 363 if (override_sni_set_) { |
387 client_->set_server_id(QuicServerId(override_sni_, url.EffectiveIntPort(), | 364 client_->set_server_id(QuicServerId(override_sni_, url.EffectiveIntPort(), |
388 PRIVACY_MODE_DISABLED)); | 365 PRIVACY_MODE_DISABLED)); |
389 } else { | |
390 if (!url.host().empty()) { | |
391 client_->set_server_id(QuicServerId(url.host(), url.EffectiveIntPort(), | |
392 PRIVACY_MODE_DISABLED)); | |
393 } | |
394 } | 366 } |
395 } | 367 } |
396 | 368 |
397 // TODO(rtenneti): Add support for HTTPMessage::body_chunks(). | 369 ssize_t ret = GetOrCreateStreamAndSendRequest(&headers, body, fin, nullptr); |
398 // CHECK(message.body_chunks().empty()) | |
399 // << "HTTPMessage::body_chunks not supported"; | |
400 | |
401 std::unique_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers())); | |
402 ssize_t ret = GetOrCreateStreamAndSendRequest( | |
403 (munged_headers.get() ? munged_headers.get() : message.headers()), | |
404 message.body(), message.has_complete_message(), nullptr); | |
405 WaitForWriteToFlush(); | 370 WaitForWriteToFlush(); |
406 return ret; | 371 return ret; |
407 } | 372 } |
408 | 373 |
409 ssize_t QuicTestClient::SendData(const string& data, bool last_data) { | 374 ssize_t QuicTestClient::SendData(const string& data, bool last_data) { |
410 return SendData(data, last_data, nullptr); | 375 return SendData(data, last_data, nullptr); |
411 } | 376 } |
412 | 377 |
413 ssize_t QuicTestClient::SendData(const string& data, | 378 ssize_t QuicTestClient::SendData(const string& data, |
414 bool last_data, | 379 bool last_data, |
(...skipping 16 matching lines...) Expand all Loading... |
431 | 396 |
432 void QuicTestClient::set_buffer_body(bool buffer_body) { | 397 void QuicTestClient::set_buffer_body(bool buffer_body) { |
433 buffer_body_ = buffer_body; | 398 buffer_body_ = buffer_body; |
434 } | 399 } |
435 | 400 |
436 const string& QuicTestClient::response_body() { | 401 const string& QuicTestClient::response_body() { |
437 return response_; | 402 return response_; |
438 } | 403 } |
439 | 404 |
440 string QuicTestClient::SendCustomSynchronousRequest( | 405 string QuicTestClient::SendCustomSynchronousRequest( |
441 const HTTPMessage& message) { | 406 const SpdyHeaderBlock& headers, |
442 if (SendMessage(message) == 0) { | 407 const string& body) { |
443 DLOG(ERROR) << "Failed the request for uri:" | 408 if (SendMessage(headers, body) == 0) { |
444 << message.headers()->request_uri(); | 409 DLOG(ERROR) << "Failed the request for: " << headers.DebugString(); |
445 // Set the response_ explicitly. Otherwise response_ will contain the | 410 // Set the response_ explicitly. Otherwise response_ will contain the |
446 // response from the previously successful request. | 411 // response from the previously successful request. |
447 response_ = ""; | 412 response_ = ""; |
448 } else { | 413 } else { |
449 WaitForResponse(); | 414 WaitForResponse(); |
450 } | 415 } |
451 return response_; | 416 return response_; |
452 } | 417 } |
453 | 418 |
454 string QuicTestClient::SendSynchronousRequest(const string& uri) { | 419 string QuicTestClient::SendSynchronousRequest(const string& uri) { |
455 HTTPMessage message; | 420 SpdyHeaderBlock headers; |
456 FillInRequest(uri, &message); | 421 if (!PopulateHeaderBlockFromUrl(uri, &headers)) { |
457 return SendCustomSynchronousRequest(message); | 422 return ""; |
| 423 } |
| 424 return SendCustomSynchronousRequest(headers, ""); |
458 } | 425 } |
459 | 426 |
460 void QuicTestClient::SetStream(QuicSpdyClientStream* stream) { | 427 void QuicTestClient::SetStream(QuicSpdyClientStream* stream) { |
461 stream_ = stream; | 428 stream_ = stream; |
462 if (stream_ != nullptr) { | 429 if (stream_ != nullptr) { |
463 response_complete_ = false; | 430 response_complete_ = false; |
464 stream_->set_visitor(this); | 431 stream_->set_visitor(this); |
465 } | 432 } |
466 } | 433 } |
467 | 434 |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 return client_->server_address(); | 666 return client_->server_address(); |
700 } | 667 } |
701 | 668 |
702 void QuicTestClient::WaitForWriteToFlush() { | 669 void QuicTestClient::WaitForWriteToFlush() { |
703 while (connected() && client()->session()->HasDataToWrite()) { | 670 while (connected() && client()->session()->HasDataToWrite()) { |
704 client_->WaitForEvents(); | 671 client_->WaitForEvents(); |
705 } | 672 } |
706 } | 673 } |
707 | 674 |
708 void QuicTestClient::TestClientDataToResend::Resend() { | 675 void QuicTestClient::TestClientDataToResend::Resend() { |
709 BalsaHeaders balsa_headers; | 676 test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_, |
710 SpdyBalsaUtils::SpdyHeadersToRequestHeaders(*headers_, &balsa_headers); | |
711 test_client_->GetOrCreateStreamAndSendRequest(&balsa_headers, body_, fin_, | |
712 delegate_); | 677 delegate_); |
713 headers_.reset(); | 678 headers_.reset(); |
714 } | 679 } |
715 | 680 |
716 // static | 681 bool QuicTestClient::PopulateHeaderBlockFromUrl(const string& uri, |
717 void QuicTestClient::FillInRequest(const string& uri, HTTPMessage* message) { | 682 SpdyHeaderBlock* headers) { |
718 CHECK(message); | 683 string url; |
719 message->headers()->SetRequestVersion( | 684 if (base::StartsWith(uri, "https://", base::CompareCase::INSENSITIVE_ASCII) || |
720 HTTPMessage::VersionToString(HttpConstants::HTTP_1_1)); | 685 base::StartsWith(uri, "http://", base::CompareCase::INSENSITIVE_ASCII)) { |
721 message->headers()->SetRequestMethod( | 686 url = uri; |
722 HTTPMessage::MethodToString(HttpConstants::GET)); | 687 } else if (uri[0] == '/') { |
723 message->headers()->SetRequestUri(uri); | 688 url = "https://" + client_->server_id().host() + uri; |
| 689 } else { |
| 690 url = "https://" + uri; |
| 691 } |
| 692 return SpdyUtils::PopulateHeaderBlockFromUrl(url, headers); |
724 } | 693 } |
725 | 694 |
726 } // namespace test | 695 } // namespace test |
727 } // namespace net | 696 } // namespace net |
OLD | NEW |