Home | History | Annotate | Download | only in test_tools
      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