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 3 // found in the LICENSE file. 4 5 #include "net/tools/quic/test_tools/quic_test_client.h" 6 7 #include "base/time/time.h" 8 #include "net/base/completion_callback.h" 9 #include "net/base/net_errors.h" 10 #include "net/cert/cert_verify_result.h" 11 #include "net/cert/x509_certificate.h" 12 #include "net/quic/crypto/proof_verifier.h" 13 #include "net/quic/quic_server_id.h" 14 #include "net/quic/test_tools/quic_connection_peer.h" 15 #include "net/quic/test_tools/quic_session_peer.h" 16 #include "net/quic/test_tools/quic_test_utils.h" 17 #include "net/quic/test_tools/reliable_quic_stream_peer.h" 18 #include "net/tools/balsa/balsa_headers.h" 19 #include "net/tools/quic/quic_epoll_connection_helper.h" 20 #include "net/tools/quic/quic_packet_writer_wrapper.h" 21 #include "net/tools/quic/quic_spdy_client_stream.h" 22 #include "net/tools/quic/test_tools/http_message.h" 23 #include "net/tools/quic/test_tools/quic_client_peer.h" 24 #include "url/gurl.h" 25 26 using base::StringPiece; 27 using net::QuicServerId; 28 using net::test::QuicConnectionPeer; 29 using net::test::QuicSessionPeer; 30 using net::test::ReliableQuicStreamPeer; 31 using std::string; 32 using std::vector; 33 34 namespace net { 35 namespace tools { 36 namespace test { 37 namespace { 38 39 // RecordingProofVerifier accepts any certificate chain and records the common 40 // name of the leaf. 41 class RecordingProofVerifier : public ProofVerifier { 42 public: 43 // ProofVerifier interface. 44 virtual QuicAsyncStatus VerifyProof( 45 const string& hostname, 46 const string& server_config, 47 const vector<string>& certs, 48 const string& signature, 49 const ProofVerifyContext* context, 50 string* error_details, 51 scoped_ptr<ProofVerifyDetails>* details, 52 ProofVerifierCallback* callback) OVERRIDE { 53 common_name_.clear(); 54 if (certs.empty()) { 55 return QUIC_FAILURE; 56 } 57 58 // Convert certs to X509Certificate. 59 vector<StringPiece> cert_pieces(certs.size()); 60 for (unsigned i = 0; i < certs.size(); i++) { 61 cert_pieces[i] = StringPiece(certs[i]); 62 } 63 scoped_refptr<net::X509Certificate> cert = 64 net::X509Certificate::CreateFromDERCertChain(cert_pieces); 65 if (!cert.get()) { 66 return QUIC_FAILURE; 67 } 68 69 common_name_ = cert->subject().GetDisplayName(); 70 return QUIC_SUCCESS; 71 } 72 73 const string& common_name() const { return common_name_; } 74 75 private: 76 string common_name_; 77 }; 78 79 } // anonymous namespace 80 81 BalsaHeaders* MungeHeaders(const BalsaHeaders* const_headers, 82 bool secure) { 83 StringPiece uri = const_headers->request_uri(); 84 if (uri.empty()) { 85 return NULL; 86 } 87 if (const_headers->request_method() == "CONNECT") { 88 return NULL; 89 } 90 BalsaHeaders* headers = new BalsaHeaders; 91 headers->CopyFrom(*const_headers); 92 if (!uri.starts_with("https://") && 93 !uri.starts_with("http://")) { 94 // If we have a relative URL, set some defaults. 95 string full_uri = secure ? "https://www.google.com" : 96 "http://www.google.com"; 97 full_uri.append(uri.as_string()); 98 headers->SetRequestUri(full_uri); 99 } 100 return headers; 101 } 102 103 MockableQuicClient::MockableQuicClient( 104 IPEndPoint server_address, 105 const QuicServerId& server_id, 106 const QuicVersionVector& supported_versions, 107 EpollServer* epoll_server) 108 : QuicClient(server_address, 109 server_id, 110 supported_versions, 111 false, 112 epoll_server), 113 override_connection_id_(0), 114 test_writer_(NULL) {} 115 116 MockableQuicClient::MockableQuicClient( 117 IPEndPoint server_address, 118 const QuicServerId& server_id, 119 const QuicConfig& config, 120 const QuicVersionVector& supported_versions, 121 EpollServer* epoll_server) 122 : QuicClient(server_address, 123 server_id, 124 supported_versions, 125 false, 126 config, 127 epoll_server), 128 override_connection_id_(0), 129 test_writer_(NULL) {} 130 131 MockableQuicClient::~MockableQuicClient() { 132 if (connected()) { 133 Disconnect(); 134 } 135 } 136 137 QuicPacketWriter* MockableQuicClient::CreateQuicPacketWriter() { 138 QuicPacketWriter* writer = QuicClient::CreateQuicPacketWriter(); 139 if (!test_writer_) { 140 return writer; 141 } 142 test_writer_->set_writer(writer); 143 return test_writer_; 144 } 145 146 QuicConnectionId MockableQuicClient::GenerateConnectionId() { 147 return override_connection_id_ ? override_connection_id_ 148 : QuicClient::GenerateConnectionId(); 149 } 150 151 // Takes ownership of writer. 152 void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) { 153 CHECK(test_writer_ == NULL); 154 test_writer_ = writer; 155 } 156 157 void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) { 158 override_connection_id_ = connection_id; 159 } 160 161 QuicTestClient::QuicTestClient(IPEndPoint server_address, 162 const string& server_hostname, 163 const QuicVersionVector& supported_versions) 164 : client_(new MockableQuicClient(server_address, 165 QuicServerId(server_hostname, 166 server_address.port(), 167 false, 168 PRIVACY_MODE_DISABLED), 169 supported_versions, 170 &epoll_server_)) { 171 Initialize(true); 172 } 173 174 QuicTestClient::QuicTestClient(IPEndPoint server_address, 175 const string& server_hostname, 176 bool secure, 177 const QuicVersionVector& supported_versions) 178 : client_(new MockableQuicClient(server_address, 179 QuicServerId(server_hostname, 180 server_address.port(), 181 secure, 182 PRIVACY_MODE_DISABLED), 183 supported_versions, 184 &epoll_server_)) { 185 Initialize(secure); 186 } 187 188 QuicTestClient::QuicTestClient( 189 IPEndPoint server_address, 190 const string& server_hostname, 191 bool secure, 192 const QuicConfig& config, 193 const QuicVersionVector& supported_versions) 194 : client_( 195 new MockableQuicClient(server_address, 196 QuicServerId(server_hostname, 197 server_address.port(), 198 secure, 199 PRIVACY_MODE_DISABLED), 200 config, 201 supported_versions, 202 &epoll_server_)) { 203 Initialize(secure); 204 } 205 206 QuicTestClient::QuicTestClient() { 207 } 208 209 QuicTestClient::~QuicTestClient() { 210 if (stream_) { 211 stream_->set_visitor(NULL); 212 } 213 } 214 215 void QuicTestClient::Initialize(bool secure) { 216 priority_ = 3; 217 connect_attempted_ = false; 218 secure_ = secure; 219 auto_reconnect_ = false; 220 buffer_body_ = true; 221 fec_policy_ = FEC_PROTECT_OPTIONAL; 222 proof_verifier_ = NULL; 223 ClearPerRequestState(); 224 ExpectCertificates(secure_); 225 } 226 227 void QuicTestClient::ExpectCertificates(bool on) { 228 if (on) { 229 proof_verifier_ = new RecordingProofVerifier; 230 client_->SetProofVerifier(proof_verifier_); 231 } else { 232 proof_verifier_ = NULL; 233 client_->SetProofVerifier(NULL); 234 } 235 } 236 237 void QuicTestClient::SetUserAgentID(const string& user_agent_id) { 238 client_->SetUserAgentID(user_agent_id); 239 } 240 241 ssize_t QuicTestClient::SendRequest(const string& uri) { 242 HTTPMessage message(HttpConstants::HTTP_1_1, 243 HttpConstants::GET, 244 uri); 245 return SendMessage(message); 246 } 247 248 ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) { 249 stream_ = NULL; // Always force creation of a stream for SendMessage. 250 251 // If we're not connected, try to find an sni hostname. 252 if (!connected()) { 253 GURL url(message.headers()->request_uri().as_string()); 254 if (!url.host().empty()) { 255 client_->set_server_id( 256 QuicServerId(url.host(), 257 url.EffectiveIntPort(), 258 url.SchemeIs("https"), 259 PRIVACY_MODE_DISABLED)); 260 } 261 } 262 263 QuicSpdyClientStream* stream = GetOrCreateStream(); 264 if (!stream) { return 0; } 265 266 scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(), 267 secure_)); 268 ssize_t ret = GetOrCreateStream()->SendRequest( 269 munged_headers.get() ? *munged_headers.get() : *message.headers(), 270 message.body(), 271 message.has_complete_message()); 272 WaitForWriteToFlush(); 273 return ret; 274 } 275 276 ssize_t QuicTestClient::SendData(string data, bool last_data) { 277 QuicSpdyClientStream* stream = GetOrCreateStream(); 278 if (!stream) { return 0; } 279 GetOrCreateStream()->SendBody(data, last_data); 280 WaitForWriteToFlush(); 281 return data.length(); 282 } 283 284 bool QuicTestClient::response_complete() const { 285 return response_complete_; 286 } 287 288 int QuicTestClient::response_header_size() const { 289 return response_header_size_; 290 } 291 292 int64 QuicTestClient::response_body_size() const { 293 return response_body_size_; 294 } 295 296 bool QuicTestClient::buffer_body() const { 297 return buffer_body_; 298 } 299 300 void QuicTestClient::set_buffer_body(bool buffer_body) { 301 buffer_body_ = buffer_body; 302 } 303 304 bool QuicTestClient::ServerInLameDuckMode() const { 305 return false; 306 } 307 308 const string& QuicTestClient::response_body() { 309 return response_; 310 } 311 312 string QuicTestClient::SendCustomSynchronousRequest( 313 const HTTPMessage& message) { 314 SendMessage(message); 315 WaitForResponse(); 316 return response_; 317 } 318 319 string QuicTestClient::SendSynchronousRequest(const string& uri) { 320 if (SendRequest(uri) == 0) { 321 DLOG(ERROR) << "Failed the request for uri:" << uri; 322 return ""; 323 } 324 WaitForResponse(); 325 return response_; 326 } 327 328 QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() { 329 if (!connect_attempted_ || auto_reconnect_) { 330 if (!connected()) { 331 Connect(); 332 } 333 if (!connected()) { 334 return NULL; 335 } 336 } 337 if (!stream_) { 338 stream_ = client_->CreateReliableClientStream(); 339 if (stream_ == NULL) { 340 return NULL; 341 } 342 stream_->set_visitor(this); 343 reinterpret_cast<QuicSpdyClientStream*>(stream_)->set_priority(priority_); 344 // Set FEC policy on stream. 345 ReliableQuicStreamPeer::SetFecPolicy(stream_, fec_policy_); 346 } 347 348 return stream_; 349 } 350 351 QuicErrorCode QuicTestClient::connection_error() { 352 return client()->session()->error(); 353 } 354 355 MockableQuicClient* QuicTestClient::client() { return client_.get(); } 356 357 const string& QuicTestClient::cert_common_name() const { 358 return reinterpret_cast<RecordingProofVerifier*>(proof_verifier_) 359 ->common_name(); 360 } 361 362 QuicTagValueMap QuicTestClient::GetServerConfig() const { 363 QuicCryptoClientConfig* config = 364 QuicClientPeer::GetCryptoConfig(client_.get()); 365 QuicCryptoClientConfig::CachedState* state = 366 config->LookupOrCreate(client_->server_id()); 367 const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig(); 368 if (handshake_msg != NULL) { 369 return handshake_msg->tag_value_map(); 370 } else { 371 return QuicTagValueMap(); 372 } 373 } 374 375 bool QuicTestClient::connected() const { 376 return client_->connected(); 377 } 378 379 void QuicTestClient::Connect() { 380 DCHECK(!connected()); 381 if (!connect_attempted_) { 382 client_->Initialize(); 383 } 384 client_->Connect(); 385 connect_attempted_ = true; 386 } 387 388 void QuicTestClient::ResetConnection() { 389 Disconnect(); 390 Connect(); 391 } 392 393 void QuicTestClient::Disconnect() { 394 client_->Disconnect(); 395 connect_attempted_ = false; 396 } 397 398 IPEndPoint QuicTestClient::LocalSocketAddress() const { 399 return client_->client_address(); 400 } 401 402 void QuicTestClient::ClearPerRequestState() { 403 stream_error_ = QUIC_STREAM_NO_ERROR; 404 stream_ = NULL; 405 response_ = ""; 406 response_complete_ = false; 407 response_headers_complete_ = false; 408 headers_.Clear(); 409 bytes_read_ = 0; 410 bytes_written_ = 0; 411 response_header_size_ = 0; 412 response_body_size_ = 0; 413 } 414 415 void QuicTestClient::WaitForResponseForMs(int timeout_ms) { 416 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond; 417 int64 old_timeout_us = epoll_server()->timeout_in_us(); 418 if (timeout_us > 0) { 419 epoll_server()->set_timeout_in_us(timeout_us); 420 } 421 const QuicClock* clock = 422 QuicConnectionPeer::GetHelper(client()->session()->connection())-> 423 GetClock(); 424 QuicTime end_waiting_time = clock->Now().Add( 425 QuicTime::Delta::FromMicroseconds(timeout_us)); 426 while (stream_ != NULL && 427 !client_->session()->IsClosedStream(stream_->id()) && 428 (timeout_us < 0 || clock->Now() < end_waiting_time)) { 429 client_->WaitForEvents(); 430 } 431 if (timeout_us > 0) { 432 epoll_server()->set_timeout_in_us(old_timeout_us); 433 } 434 } 435 436 void QuicTestClient::WaitForInitialResponseForMs(int timeout_ms) { 437 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond; 438 int64 old_timeout_us = epoll_server()->timeout_in_us(); 439 if (timeout_us > 0) { 440 epoll_server()->set_timeout_in_us(timeout_us); 441 } 442 const QuicClock* clock = 443 QuicConnectionPeer::GetHelper(client()->session()->connection())-> 444 GetClock(); 445 QuicTime end_waiting_time = clock->Now().Add( 446 QuicTime::Delta::FromMicroseconds(timeout_us)); 447 while (stream_ != NULL && 448 !client_->session()->IsClosedStream(stream_->id()) && 449 stream_->stream_bytes_read() == 0 && 450 (timeout_us < 0 || clock->Now() < end_waiting_time)) { 451 client_->WaitForEvents(); 452 } 453 if (timeout_us > 0) { 454 epoll_server()->set_timeout_in_us(old_timeout_us); 455 } 456 } 457 458 ssize_t QuicTestClient::Send(const void *buffer, size_t size) { 459 return SendData(string(static_cast<const char*>(buffer), size), false); 460 } 461 462 bool QuicTestClient::response_headers_complete() const { 463 if (stream_ != NULL) { 464 return stream_->headers_decompressed(); 465 } else { 466 return response_headers_complete_; 467 } 468 } 469 470 const BalsaHeaders* QuicTestClient::response_headers() const { 471 if (stream_ != NULL) { 472 return &stream_->headers(); 473 } else { 474 return &headers_; 475 } 476 } 477 478 int64 QuicTestClient::response_size() const { 479 return bytes_read_; 480 } 481 482 size_t QuicTestClient::bytes_read() const { 483 return bytes_read_; 484 } 485 486 size_t QuicTestClient::bytes_written() const { 487 return bytes_written_; 488 } 489 490 void QuicTestClient::OnClose(QuicDataStream* stream) { 491 if (stream_ != stream) { 492 return; 493 } 494 if (buffer_body()) { 495 // TODO(fnk): The stream still buffers the whole thing. Fix that. 496 response_ = stream_->data(); 497 } 498 response_complete_ = true; 499 response_headers_complete_ = stream_->headers_decompressed(); 500 headers_.CopyFrom(stream_->headers()); 501 stream_error_ = stream_->stream_error(); 502 bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read(); 503 bytes_written_ = 504 stream_->stream_bytes_written() + stream_->header_bytes_written(); 505 response_header_size_ = headers_.GetSizeForWriteBuffer(); 506 response_body_size_ = stream_->data().size(); 507 stream_ = NULL; 508 } 509 510 void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) { 511 client_->UseWriter(writer); 512 } 513 514 void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) { 515 DCHECK(!connected()); 516 client_->UseConnectionId(connection_id); 517 } 518 519 ssize_t QuicTestClient::SendAndWaitForResponse(const void *buffer, 520 size_t size) { 521 LOG(DFATAL) << "Not implemented"; 522 return 0; 523 } 524 525 void QuicTestClient::Bind(IPEndPoint* local_address) { 526 DLOG(WARNING) << "Bind will be done during connect"; 527 } 528 529 string QuicTestClient::SerializeMessage(const HTTPMessage& message) { 530 LOG(DFATAL) << "Not implemented"; 531 return ""; 532 } 533 534 IPAddressNumber QuicTestClient::bind_to_address() const { 535 return client_->bind_to_address(); 536 } 537 538 void QuicTestClient::set_bind_to_address(IPAddressNumber address) { 539 client_->set_bind_to_address(address); 540 } 541 542 const IPEndPoint& QuicTestClient::address() const { 543 LOG(DFATAL) << "Not implemented"; 544 return client_->server_address(); 545 } 546 547 size_t QuicTestClient::requests_sent() const { 548 LOG(DFATAL) << "Not implemented"; 549 return 0; 550 } 551 552 void QuicTestClient::WaitForWriteToFlush() { 553 while (connected() && client()->session()->HasDataToWrite()) { 554 client_->WaitForEvents(); 555 } 556 } 557 558 void QuicTestClient::SetFecPolicy(FecPolicy fec_policy) { 559 fec_policy_ = fec_policy; 560 // Set policy for headers and crypto streams. 561 ReliableQuicStreamPeer::SetFecPolicy( 562 QuicSessionPeer::GetHeadersStream(client()->session()), fec_policy); 563 ReliableQuicStreamPeer::SetFecPolicy(client()->session()->GetCryptoStream(), 564 fec_policy); 565 } 566 567 } // namespace test 568 } // namespace tools 569 } // namespace net 570