Home | History | Annotate | Download | only in dns
      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/dns/dns_transaction.h"
      6 
      7 #include <deque>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/bind.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/scoped_vector.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "base/message_loop/message_loop.h"
     17 #include "base/metrics/histogram.h"
     18 #include "base/rand_util.h"
     19 #include "base/stl_util.h"
     20 #include "base/strings/string_piece.h"
     21 #include "base/threading/non_thread_safe.h"
     22 #include "base/timer/timer.h"
     23 #include "base/values.h"
     24 #include "net/base/big_endian.h"
     25 #include "net/base/completion_callback.h"
     26 #include "net/base/dns_util.h"
     27 #include "net/base/io_buffer.h"
     28 #include "net/base/ip_endpoint.h"
     29 #include "net/base/net_errors.h"
     30 #include "net/base/net_log.h"
     31 #include "net/dns/dns_protocol.h"
     32 #include "net/dns/dns_query.h"
     33 #include "net/dns/dns_response.h"
     34 #include "net/dns/dns_session.h"
     35 #include "net/socket/stream_socket.h"
     36 #include "net/udp/datagram_client_socket.h"
     37 
     38 namespace net {
     39 
     40 namespace {
     41 
     42 // Provide a common macro to simplify code and readability. We must use a
     43 // macro as the underlying HISTOGRAM macro creates static variables.
     44 #define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \
     45     base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100)
     46 
     47 // Count labels in the fully-qualified name in DNS format.
     48 int CountLabels(const std::string& name) {
     49   size_t count = 0;
     50   for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1)
     51     ++count;
     52   return count;
     53 }
     54 
     55 bool IsIPLiteral(const std::string& hostname) {
     56   IPAddressNumber ip;
     57   return ParseIPLiteralToNumber(hostname, &ip);
     58 }
     59 
     60 base::Value* NetLogStartCallback(const std::string* hostname,
     61                            uint16 qtype,
     62                            NetLog::LogLevel /* log_level */) {
     63   base::DictionaryValue* dict = new base::DictionaryValue();
     64   dict->SetString("hostname", *hostname);
     65   dict->SetInteger("query_type", qtype);
     66   return dict;
     67 };
     68 
     69 // ----------------------------------------------------------------------------
     70 
     71 // A single asynchronous DNS exchange, which consists of sending out a
     72 // DNS query, waiting for a response, and returning the response that it
     73 // matches. Logging is done in the socket and in the outer DnsTransaction.
     74 class DnsAttempt {
     75  public:
     76   explicit DnsAttempt(unsigned server_index)
     77       : result_(ERR_FAILED), server_index_(server_index) {}
     78 
     79   virtual ~DnsAttempt() {}
     80   // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously
     81   // and calls |callback| upon completion.
     82   virtual int Start(const CompletionCallback& callback) = 0;
     83 
     84   // Returns the query of this attempt.
     85   virtual const DnsQuery* GetQuery() const = 0;
     86 
     87   // Returns the response or NULL if has not received a matching response from
     88   // the server.
     89   virtual const DnsResponse* GetResponse() const = 0;
     90 
     91   // Returns the net log bound to the source of the socket.
     92   virtual const BoundNetLog& GetSocketNetLog() const = 0;
     93 
     94   // Returns the index of the destination server within DnsConfig::nameservers.
     95   unsigned server_index() const { return server_index_; }
     96 
     97   // Returns a Value representing the received response, along with a reference
     98   // to the NetLog source source of the UDP socket used.  The request must have
     99   // completed before this is called.
    100   base::Value* NetLogResponseCallback(NetLog::LogLevel log_level) const {
    101     DCHECK(GetResponse()->IsValid());
    102 
    103     base::DictionaryValue* dict = new base::DictionaryValue();
    104     dict->SetInteger("rcode", GetResponse()->rcode());
    105     dict->SetInteger("answer_count", GetResponse()->answer_count());
    106     GetSocketNetLog().source().AddToEventParameters(dict);
    107     return dict;
    108   }
    109 
    110   void set_result(int result) {
    111     result_ = result;
    112   }
    113 
    114   // True if current attempt is pending (waiting for server response).
    115   bool is_pending() const {
    116     return result_ == ERR_IO_PENDING;
    117   }
    118 
    119   // True if attempt is completed (received server response).
    120   bool is_completed() const {
    121     return (result_ == OK) || (result_ == ERR_NAME_NOT_RESOLVED) ||
    122         (result_ == ERR_DNS_SERVER_REQUIRES_TCP);
    123   }
    124 
    125  private:
    126   // Result of last operation.
    127   int result_;
    128 
    129   const unsigned server_index_;
    130 };
    131 
    132 class DnsUDPAttempt : public DnsAttempt {
    133  public:
    134   DnsUDPAttempt(unsigned server_index,
    135                 scoped_ptr<DnsSession::SocketLease> socket_lease,
    136                 scoped_ptr<DnsQuery> query)
    137       : DnsAttempt(server_index),
    138         next_state_(STATE_NONE),
    139         received_malformed_response_(false),
    140         socket_lease_(socket_lease.Pass()),
    141         query_(query.Pass()) {}
    142 
    143   // DnsAttempt:
    144   virtual int Start(const CompletionCallback& callback) OVERRIDE {
    145     DCHECK_EQ(STATE_NONE, next_state_);
    146     callback_ = callback;
    147     start_time_ = base::TimeTicks::Now();
    148     next_state_ = STATE_SEND_QUERY;
    149     return DoLoop(OK);
    150   }
    151 
    152   virtual const DnsQuery* GetQuery() const OVERRIDE {
    153     return query_.get();
    154   }
    155 
    156   virtual const DnsResponse* GetResponse() const OVERRIDE {
    157     const DnsResponse* resp = response_.get();
    158     return (resp != NULL && resp->IsValid()) ? resp : NULL;
    159   }
    160 
    161   virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE {
    162     return socket_lease_->socket()->NetLog();
    163   }
    164 
    165  private:
    166   enum State {
    167     STATE_SEND_QUERY,
    168     STATE_SEND_QUERY_COMPLETE,
    169     STATE_READ_RESPONSE,
    170     STATE_READ_RESPONSE_COMPLETE,
    171     STATE_NONE,
    172   };
    173 
    174   DatagramClientSocket* socket() {
    175     return socket_lease_->socket();
    176   }
    177 
    178   int DoLoop(int result) {
    179     CHECK_NE(STATE_NONE, next_state_);
    180     int rv = result;
    181     do {
    182       State state = next_state_;
    183       next_state_ = STATE_NONE;
    184       switch (state) {
    185         case STATE_SEND_QUERY:
    186           rv = DoSendQuery();
    187           break;
    188         case STATE_SEND_QUERY_COMPLETE:
    189           rv = DoSendQueryComplete(rv);
    190           break;
    191         case STATE_READ_RESPONSE:
    192           rv = DoReadResponse();
    193           break;
    194         case STATE_READ_RESPONSE_COMPLETE:
    195           rv = DoReadResponseComplete(rv);
    196           break;
    197         default:
    198           NOTREACHED();
    199           break;
    200       }
    201     } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    202 
    203     set_result(rv);
    204     // If we received a malformed response, and are now waiting for another one,
    205     // indicate to the transaction that the server might be misbehaving.
    206     if (rv == ERR_IO_PENDING && received_malformed_response_)
    207       return ERR_DNS_MALFORMED_RESPONSE;
    208     if (rv == OK) {
    209       DCHECK_EQ(STATE_NONE, next_state_);
    210       DNS_HISTOGRAM("AsyncDNS.UDPAttemptSuccess",
    211                     base::TimeTicks::Now() - start_time_);
    212     } else if (rv != ERR_IO_PENDING) {
    213       DNS_HISTOGRAM("AsyncDNS.UDPAttemptFail",
    214                     base::TimeTicks::Now() - start_time_);
    215     }
    216     return rv;
    217   }
    218 
    219   int DoSendQuery() {
    220     next_state_ = STATE_SEND_QUERY_COMPLETE;
    221     return socket()->Write(query_->io_buffer(),
    222                            query_->io_buffer()->size(),
    223                            base::Bind(&DnsUDPAttempt::OnIOComplete,
    224                                       base::Unretained(this)));
    225   }
    226 
    227   int DoSendQueryComplete(int rv) {
    228     DCHECK_NE(ERR_IO_PENDING, rv);
    229     if (rv < 0)
    230       return rv;
    231 
    232     // Writing to UDP should not result in a partial datagram.
    233     if (rv != query_->io_buffer()->size())
    234       return ERR_MSG_TOO_BIG;
    235 
    236     next_state_ = STATE_READ_RESPONSE;
    237     return OK;
    238   }
    239 
    240   int DoReadResponse() {
    241     next_state_ = STATE_READ_RESPONSE_COMPLETE;
    242     response_.reset(new DnsResponse());
    243     return socket()->Read(response_->io_buffer(),
    244                           response_->io_buffer()->size(),
    245                           base::Bind(&DnsUDPAttempt::OnIOComplete,
    246                                      base::Unretained(this)));
    247   }
    248 
    249   int DoReadResponseComplete(int rv) {
    250     DCHECK_NE(ERR_IO_PENDING, rv);
    251     if (rv < 0)
    252       return rv;
    253 
    254     DCHECK(rv);
    255     if (!response_->InitParse(rv, *query_)) {
    256       // Other implementations simply ignore mismatched responses. Since each
    257       // DnsUDPAttempt binds to a different port, we might find that responses
    258       // to previously timed out queries lead to failures in the future.
    259       // Our solution is to make another attempt, in case the query truly
    260       // failed, but keep this attempt alive, in case it was a false alarm.
    261       received_malformed_response_ = true;
    262       next_state_ = STATE_READ_RESPONSE;
    263       return OK;
    264     }
    265     if (response_->flags() & dns_protocol::kFlagTC)
    266       return ERR_DNS_SERVER_REQUIRES_TCP;
    267     // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051
    268     if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
    269       return ERR_NAME_NOT_RESOLVED;
    270     if (response_->rcode() != dns_protocol::kRcodeNOERROR)
    271       return ERR_DNS_SERVER_FAILED;
    272 
    273     return OK;
    274   }
    275 
    276   void OnIOComplete(int rv) {
    277     rv = DoLoop(rv);
    278     if (rv != ERR_IO_PENDING)
    279       callback_.Run(rv);
    280   }
    281 
    282   State next_state_;
    283   bool received_malformed_response_;
    284   base::TimeTicks start_time_;
    285 
    286   scoped_ptr<DnsSession::SocketLease> socket_lease_;
    287   scoped_ptr<DnsQuery> query_;
    288 
    289   scoped_ptr<DnsResponse> response_;
    290 
    291   CompletionCallback callback_;
    292 
    293   DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt);
    294 };
    295 
    296 class DnsTCPAttempt : public DnsAttempt {
    297  public:
    298   DnsTCPAttempt(unsigned server_index,
    299                 scoped_ptr<StreamSocket> socket,
    300                 scoped_ptr<DnsQuery> query)
    301       : DnsAttempt(server_index),
    302         next_state_(STATE_NONE),
    303         socket_(socket.Pass()),
    304         query_(query.Pass()),
    305         length_buffer_(new IOBufferWithSize(sizeof(uint16))),
    306         response_length_(0) {}
    307 
    308   // DnsAttempt:
    309   virtual int Start(const CompletionCallback& callback) OVERRIDE {
    310     DCHECK_EQ(STATE_NONE, next_state_);
    311     callback_ = callback;
    312     start_time_ = base::TimeTicks::Now();
    313     next_state_ = STATE_CONNECT_COMPLETE;
    314     int rv = socket_->Connect(base::Bind(&DnsTCPAttempt::OnIOComplete,
    315                                          base::Unretained(this)));
    316     if (rv == ERR_IO_PENDING) {
    317       set_result(rv);
    318       return rv;
    319     }
    320     return DoLoop(rv);
    321   }
    322 
    323   virtual const DnsQuery* GetQuery() const OVERRIDE {
    324     return query_.get();
    325   }
    326 
    327   virtual const DnsResponse* GetResponse() const OVERRIDE {
    328     const DnsResponse* resp = response_.get();
    329     return (resp != NULL && resp->IsValid()) ? resp : NULL;
    330   }
    331 
    332   virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE {
    333     return socket_->NetLog();
    334   }
    335 
    336  private:
    337   enum State {
    338     STATE_CONNECT_COMPLETE,
    339     STATE_SEND_LENGTH,
    340     STATE_SEND_QUERY,
    341     STATE_READ_LENGTH,
    342     STATE_READ_RESPONSE,
    343     STATE_NONE,
    344   };
    345 
    346   int DoLoop(int result) {
    347     CHECK_NE(STATE_NONE, next_state_);
    348     int rv = result;
    349     do {
    350       State state = next_state_;
    351       next_state_ = STATE_NONE;
    352       switch (state) {
    353         case STATE_CONNECT_COMPLETE:
    354           rv = DoConnectComplete(rv);
    355           break;
    356         case STATE_SEND_LENGTH:
    357           rv = DoSendLength(rv);
    358           break;
    359         case STATE_SEND_QUERY:
    360           rv = DoSendQuery(rv);
    361           break;
    362         case STATE_READ_LENGTH:
    363           rv = DoReadLength(rv);
    364           break;
    365         case STATE_READ_RESPONSE:
    366           rv = DoReadResponse(rv);
    367           break;
    368         default:
    369           NOTREACHED();
    370           break;
    371       }
    372     } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    373 
    374     set_result(rv);
    375     if (rv == OK) {
    376       DCHECK_EQ(STATE_NONE, next_state_);
    377       DNS_HISTOGRAM("AsyncDNS.TCPAttemptSuccess",
    378                     base::TimeTicks::Now() - start_time_);
    379     } else if (rv != ERR_IO_PENDING) {
    380       DNS_HISTOGRAM("AsyncDNS.TCPAttemptFail",
    381                     base::TimeTicks::Now() - start_time_);
    382     }
    383     return rv;
    384   }
    385 
    386   int DoConnectComplete(int rv) {
    387     DCHECK_NE(ERR_IO_PENDING, rv);
    388     if (rv < 0)
    389       return rv;
    390 
    391     WriteBigEndian<uint16>(length_buffer_->data(), query_->io_buffer()->size());
    392     buffer_ =
    393         new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size());
    394     next_state_ = STATE_SEND_LENGTH;
    395     return OK;
    396   }
    397 
    398   int DoSendLength(int rv) {
    399     DCHECK_NE(ERR_IO_PENDING, rv);
    400     if (rv < 0)
    401       return rv;
    402 
    403     buffer_->DidConsume(rv);
    404     if (buffer_->BytesRemaining() > 0) {
    405       next_state_ = STATE_SEND_LENGTH;
    406       return socket_->Write(
    407           buffer_.get(),
    408           buffer_->BytesRemaining(),
    409           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    410     }
    411     buffer_ = new DrainableIOBuffer(query_->io_buffer(),
    412                                     query_->io_buffer()->size());
    413     next_state_ = STATE_SEND_QUERY;
    414     return OK;
    415   }
    416 
    417   int DoSendQuery(int rv) {
    418     DCHECK_NE(ERR_IO_PENDING, rv);
    419     if (rv < 0)
    420       return rv;
    421 
    422     buffer_->DidConsume(rv);
    423     if (buffer_->BytesRemaining() > 0) {
    424       next_state_ = STATE_SEND_QUERY;
    425       return socket_->Write(
    426           buffer_.get(),
    427           buffer_->BytesRemaining(),
    428           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    429     }
    430     buffer_ =
    431         new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size());
    432     next_state_ = STATE_READ_LENGTH;
    433     return OK;
    434   }
    435 
    436   int DoReadLength(int rv) {
    437     DCHECK_NE(ERR_IO_PENDING, rv);
    438     if (rv < 0)
    439       return rv;
    440 
    441     buffer_->DidConsume(rv);
    442     if (buffer_->BytesRemaining() > 0) {
    443       next_state_ = STATE_READ_LENGTH;
    444       return socket_->Read(
    445           buffer_.get(),
    446           buffer_->BytesRemaining(),
    447           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    448     }
    449     ReadBigEndian<uint16>(length_buffer_->data(), &response_length_);
    450     // Check if advertised response is too short. (Optimization only.)
    451     if (response_length_ < query_->io_buffer()->size())
    452       return ERR_DNS_MALFORMED_RESPONSE;
    453     // Allocate more space so that DnsResponse::InitParse sanity check passes.
    454     response_.reset(new DnsResponse(response_length_ + 1));
    455     buffer_ = new DrainableIOBuffer(response_->io_buffer(), response_length_);
    456     next_state_ = STATE_READ_RESPONSE;
    457     return OK;
    458   }
    459 
    460   int DoReadResponse(int rv) {
    461     DCHECK_NE(ERR_IO_PENDING, rv);
    462     if (rv < 0)
    463       return rv;
    464 
    465     buffer_->DidConsume(rv);
    466     if (buffer_->BytesRemaining() > 0) {
    467       next_state_ = STATE_READ_RESPONSE;
    468       return socket_->Read(
    469           buffer_.get(),
    470           buffer_->BytesRemaining(),
    471           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    472     }
    473     if (!response_->InitParse(buffer_->BytesConsumed(), *query_))
    474       return ERR_DNS_MALFORMED_RESPONSE;
    475     if (response_->flags() & dns_protocol::kFlagTC)
    476       return ERR_UNEXPECTED;
    477     // TODO(szym): Frankly, none of these are expected.
    478     if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
    479       return ERR_NAME_NOT_RESOLVED;
    480     if (response_->rcode() != dns_protocol::kRcodeNOERROR)
    481       return ERR_DNS_SERVER_FAILED;
    482 
    483     return OK;
    484   }
    485 
    486   void OnIOComplete(int rv) {
    487     rv = DoLoop(rv);
    488     if (rv != ERR_IO_PENDING)
    489       callback_.Run(rv);
    490   }
    491 
    492   State next_state_;
    493   base::TimeTicks start_time_;
    494 
    495   scoped_ptr<StreamSocket> socket_;
    496   scoped_ptr<DnsQuery> query_;
    497   scoped_refptr<IOBufferWithSize> length_buffer_;
    498   scoped_refptr<DrainableIOBuffer> buffer_;
    499 
    500   uint16 response_length_;
    501   scoped_ptr<DnsResponse> response_;
    502 
    503   CompletionCallback callback_;
    504 
    505   DISALLOW_COPY_AND_ASSIGN(DnsTCPAttempt);
    506 };
    507 
    508 // ----------------------------------------------------------------------------
    509 
    510 // Implements DnsTransaction. Configuration is supplied by DnsSession.
    511 // The suffix list is built according to the DnsConfig from the session.
    512 // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout.
    513 // The first server to attempt on each query is given by
    514 // DnsSession::NextFirstServerIndex, and the order is round-robin afterwards.
    515 // Each server is attempted DnsConfig::attempts times.
    516 class DnsTransactionImpl : public DnsTransaction,
    517                            public base::NonThreadSafe,
    518                            public base::SupportsWeakPtr<DnsTransactionImpl> {
    519  public:
    520   DnsTransactionImpl(DnsSession* session,
    521                      const std::string& hostname,
    522                      uint16 qtype,
    523                      const DnsTransactionFactory::CallbackType& callback,
    524                      const BoundNetLog& net_log)
    525     : session_(session),
    526       hostname_(hostname),
    527       qtype_(qtype),
    528       callback_(callback),
    529       net_log_(net_log),
    530       qnames_initial_size_(0),
    531       attempts_count_(0),
    532       had_tcp_attempt_(false),
    533       first_server_index_(0) {
    534     DCHECK(session_.get());
    535     DCHECK(!hostname_.empty());
    536     DCHECK(!callback_.is_null());
    537     DCHECK(!IsIPLiteral(hostname_));
    538   }
    539 
    540   virtual ~DnsTransactionImpl() {
    541     if (!callback_.is_null()) {
    542       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION,
    543                                         ERR_ABORTED);
    544     }  // otherwise logged in DoCallback or Start
    545   }
    546 
    547   virtual const std::string& GetHostname() const OVERRIDE {
    548     DCHECK(CalledOnValidThread());
    549     return hostname_;
    550   }
    551 
    552   virtual uint16 GetType() const OVERRIDE {
    553     DCHECK(CalledOnValidThread());
    554     return qtype_;
    555   }
    556 
    557   virtual void Start() OVERRIDE {
    558     DCHECK(!callback_.is_null());
    559     DCHECK(attempts_.empty());
    560     net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION,
    561                         base::Bind(&NetLogStartCallback, &hostname_, qtype_));
    562     AttemptResult result(PrepareSearch(), NULL);
    563     if (result.rv == OK) {
    564       qnames_initial_size_ = qnames_.size();
    565       if (qtype_ == dns_protocol::kTypeA)
    566         UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchStart", qnames_.size());
    567       result = ProcessAttemptResult(StartQuery());
    568     }
    569 
    570     // Must always return result asynchronously, to avoid reentrancy.
    571     if (result.rv != ERR_IO_PENDING) {
    572       base::MessageLoop::current()->PostTask(
    573           FROM_HERE,
    574           base::Bind(&DnsTransactionImpl::DoCallback, AsWeakPtr(), result));
    575     }
    576   }
    577 
    578  private:
    579   // Wrapper for the result of a DnsUDPAttempt.
    580   struct AttemptResult {
    581     AttemptResult(int rv, const DnsAttempt* attempt)
    582         : rv(rv), attempt(attempt) {}
    583 
    584     int rv;
    585     const DnsAttempt* attempt;
    586   };
    587 
    588   // Prepares |qnames_| according to the DnsConfig.
    589   int PrepareSearch() {
    590     const DnsConfig& config = session_->config();
    591 
    592     std::string labeled_hostname;
    593     if (!DNSDomainFromDot(hostname_, &labeled_hostname))
    594       return ERR_INVALID_ARGUMENT;
    595 
    596     if (hostname_[hostname_.size() - 1] == '.') {
    597       // It's a fully-qualified name, no suffix search.
    598       qnames_.push_back(labeled_hostname);
    599       return OK;
    600     }
    601 
    602     int ndots = CountLabels(labeled_hostname) - 1;
    603 
    604     if (ndots > 0 && !config.append_to_multi_label_name) {
    605       qnames_.push_back(labeled_hostname);
    606       return OK;
    607     }
    608 
    609     // Set true when |labeled_hostname| is put on the list.
    610     bool had_hostname = false;
    611 
    612     if (ndots >= config.ndots) {
    613       qnames_.push_back(labeled_hostname);
    614       had_hostname = true;
    615     }
    616 
    617     std::string qname;
    618     for (size_t i = 0; i < config.search.size(); ++i) {
    619       // Ignore invalid (too long) combinations.
    620       if (!DNSDomainFromDot(hostname_ + "." + config.search[i], &qname))
    621         continue;
    622       if (qname.size() == labeled_hostname.size()) {
    623         if (had_hostname)
    624           continue;
    625         had_hostname = true;
    626       }
    627       qnames_.push_back(qname);
    628     }
    629 
    630     if (ndots > 0 && !had_hostname)
    631       qnames_.push_back(labeled_hostname);
    632 
    633     return qnames_.empty() ? ERR_DNS_SEARCH_EMPTY : OK;
    634   }
    635 
    636   void DoCallback(AttemptResult result) {
    637     DCHECK(!callback_.is_null());
    638     DCHECK_NE(ERR_IO_PENDING, result.rv);
    639     const DnsResponse* response = result.attempt ?
    640         result.attempt->GetResponse() : NULL;
    641     CHECK(result.rv != OK || response != NULL);
    642 
    643     timer_.Stop();
    644     RecordLostPacketsIfAny();
    645     if (result.rv == OK)
    646       UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountSuccess", attempts_count_);
    647     else
    648       UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountFail", attempts_count_);
    649 
    650     if (response && qtype_ == dns_protocol::kTypeA) {
    651       UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchRemain", qnames_.size());
    652       UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchDone",
    653                            qnames_initial_size_ - qnames_.size());
    654     }
    655 
    656     DnsTransactionFactory::CallbackType callback = callback_;
    657     callback_.Reset();
    658 
    659     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, result.rv);
    660     callback.Run(this, result.rv, response);
    661   }
    662 
    663   // Makes another attempt at the current name, |qnames_.front()|, using the
    664   // next nameserver.
    665   AttemptResult MakeAttempt() {
    666     unsigned attempt_number = attempts_.size();
    667 
    668     uint16 id = session_->NextQueryId();
    669     scoped_ptr<DnsQuery> query;
    670     if (attempts_.empty()) {
    671       query.reset(new DnsQuery(id, qnames_.front(), qtype_));
    672     } else {
    673       query.reset(attempts_[0]->GetQuery()->CloneWithNewId(id));
    674     }
    675 
    676     const DnsConfig& config = session_->config();
    677 
    678     unsigned server_index =
    679         (first_server_index_ + attempt_number) % config.nameservers.size();
    680     // Skip over known failed servers.
    681     server_index = session_->NextGoodServerIndex(server_index);
    682 
    683     scoped_ptr<DnsSession::SocketLease> lease =
    684         session_->AllocateSocket(server_index, net_log_.source());
    685 
    686     bool got_socket = !!lease.get();
    687 
    688     DnsUDPAttempt* attempt =
    689         new DnsUDPAttempt(server_index, lease.Pass(), query.Pass());
    690 
    691     attempts_.push_back(attempt);
    692     ++attempts_count_;
    693 
    694     if (!got_socket)
    695       return AttemptResult(ERR_CONNECTION_REFUSED, NULL);
    696 
    697     net_log_.AddEvent(
    698         NetLog::TYPE_DNS_TRANSACTION_ATTEMPT,
    699         attempt->GetSocketNetLog().source().ToEventParametersCallback());
    700 
    701     int rv = attempt->Start(
    702         base::Bind(&DnsTransactionImpl::OnUdpAttemptComplete,
    703                    base::Unretained(this), attempt_number,
    704                    base::TimeTicks::Now()));
    705     if (rv == ERR_IO_PENDING) {
    706       base::TimeDelta timeout = session_->NextTimeout(server_index,
    707                                                       attempt_number);
    708       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout);
    709     }
    710     return AttemptResult(rv, attempt);
    711   }
    712 
    713   AttemptResult MakeTCPAttempt(const DnsAttempt* previous_attempt) {
    714     DCHECK(previous_attempt);
    715     DCHECK(!had_tcp_attempt_);
    716 
    717     unsigned server_index = previous_attempt->server_index();
    718 
    719     scoped_ptr<StreamSocket> socket(
    720         session_->CreateTCPSocket(server_index, net_log_.source()));
    721 
    722     // TODO(szym): Reuse the same id to help the server?
    723     uint16 id = session_->NextQueryId();
    724     scoped_ptr<DnsQuery> query(
    725         previous_attempt->GetQuery()->CloneWithNewId(id));
    726 
    727     RecordLostPacketsIfAny();
    728     // Cancel all other attempts, no point waiting on them.
    729     attempts_.clear();
    730 
    731     unsigned attempt_number = attempts_.size();
    732 
    733     DnsTCPAttempt* attempt = new DnsTCPAttempt(server_index, socket.Pass(),
    734                                                query.Pass());
    735 
    736     attempts_.push_back(attempt);
    737     ++attempts_count_;
    738     had_tcp_attempt_ = true;
    739 
    740     net_log_.AddEvent(
    741         NetLog::TYPE_DNS_TRANSACTION_TCP_ATTEMPT,
    742         attempt->GetSocketNetLog().source().ToEventParametersCallback());
    743 
    744     int rv = attempt->Start(base::Bind(&DnsTransactionImpl::OnAttemptComplete,
    745                                        base::Unretained(this),
    746                                        attempt_number));
    747     if (rv == ERR_IO_PENDING) {
    748       // Custom timeout for TCP attempt.
    749       base::TimeDelta timeout = timer_.GetCurrentDelay() * 2;
    750       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout);
    751     }
    752     return AttemptResult(rv, attempt);
    753   }
    754 
    755   // Begins query for the current name. Makes the first attempt.
    756   AttemptResult StartQuery() {
    757     std::string dotted_qname = DNSDomainToString(qnames_.front());
    758     net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    759                         NetLog::StringCallback("qname", &dotted_qname));
    760 
    761     first_server_index_ = session_->NextFirstServerIndex();
    762     RecordLostPacketsIfAny();
    763     attempts_.clear();
    764     had_tcp_attempt_ = false;
    765     return MakeAttempt();
    766   }
    767 
    768   void OnUdpAttemptComplete(unsigned attempt_number,
    769                             base::TimeTicks start,
    770                             int rv) {
    771     DCHECK_LT(attempt_number, attempts_.size());
    772     const DnsAttempt* attempt = attempts_[attempt_number];
    773     if (attempt->GetResponse()) {
    774       session_->RecordRTT(attempt->server_index(),
    775                           base::TimeTicks::Now() - start);
    776     }
    777     OnAttemptComplete(attempt_number, rv);
    778   }
    779 
    780   void OnAttemptComplete(unsigned attempt_number, int rv) {
    781     if (callback_.is_null())
    782       return;
    783     DCHECK_LT(attempt_number, attempts_.size());
    784     const DnsAttempt* attempt = attempts_[attempt_number];
    785     AttemptResult result = ProcessAttemptResult(AttemptResult(rv, attempt));
    786     if (result.rv != ERR_IO_PENDING)
    787       DoCallback(result);
    788   }
    789 
    790   // Record packet loss for any incomplete attempts.
    791   void RecordLostPacketsIfAny() {
    792     // Loop through attempts until we find first that is completed
    793     size_t first_completed = 0;
    794     for (first_completed = 0; first_completed < attempts_.size();
    795         ++first_completed) {
    796       if (attempts_[first_completed]->is_completed())
    797         break;
    798     }
    799     // If there were no completed attempts, then we must be offline, so don't
    800     // record any attempts as lost packets.
    801     if (first_completed == attempts_.size())
    802       return;
    803 
    804     size_t num_servers = session_->config().nameservers.size();
    805     std::vector<int> server_attempts(num_servers);
    806     for (size_t i = 0; i < first_completed; ++i) {
    807       unsigned server_index = attempts_[i]->server_index();
    808       int server_attempt = server_attempts[server_index]++;
    809       // Don't record lost packet unless attempt is in pending state.
    810       if (!attempts_[i]->is_pending())
    811         continue;
    812       session_->RecordLostPacket(server_index, server_attempt);
    813     }
    814   }
    815 
    816   void LogResponse(const DnsAttempt* attempt) {
    817     if (attempt && attempt->GetResponse()) {
    818       net_log_.AddEvent(
    819           NetLog::TYPE_DNS_TRANSACTION_RESPONSE,
    820           base::Bind(&DnsAttempt::NetLogResponseCallback,
    821                      base::Unretained(attempt)));
    822     }
    823   }
    824 
    825   bool MoreAttemptsAllowed() const {
    826     if (had_tcp_attempt_)
    827       return false;
    828     const DnsConfig& config = session_->config();
    829     return attempts_.size() < config.attempts * config.nameservers.size();
    830   }
    831 
    832   // Resolves the result of a DnsAttempt until a terminal result is reached
    833   // or it will complete asynchronously (ERR_IO_PENDING).
    834   AttemptResult ProcessAttemptResult(AttemptResult result) {
    835     while (result.rv != ERR_IO_PENDING) {
    836       LogResponse(result.attempt);
    837 
    838       switch (result.rv) {
    839         case OK:
    840           session_->RecordServerSuccess(result.attempt->server_index());
    841           net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    842                                             result.rv);
    843           DCHECK(result.attempt);
    844           DCHECK(result.attempt->GetResponse());
    845           return result;
    846         case ERR_NAME_NOT_RESOLVED:
    847           session_->RecordServerSuccess(result.attempt->server_index());
    848           net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    849                                             result.rv);
    850           // Try next suffix.
    851           qnames_.pop_front();
    852           if (qnames_.empty()) {
    853             return AttemptResult(ERR_NAME_NOT_RESOLVED, NULL);
    854           } else {
    855             result = StartQuery();
    856           }
    857           break;
    858         case ERR_CONNECTION_REFUSED:
    859         case ERR_DNS_TIMED_OUT:
    860           if (result.attempt)
    861             session_->RecordServerFailure(result.attempt->server_index());
    862           if (MoreAttemptsAllowed()) {
    863             result = MakeAttempt();
    864           } else {
    865             return result;
    866           }
    867           break;
    868         case ERR_DNS_SERVER_REQUIRES_TCP:
    869           result = MakeTCPAttempt(result.attempt);
    870           break;
    871         default:
    872           // Server failure.
    873           DCHECK(result.attempt);
    874           if (result.attempt != attempts_.back()) {
    875             // This attempt already timed out. Ignore it.
    876             session_->RecordServerFailure(result.attempt->server_index());
    877             return AttemptResult(ERR_IO_PENDING, NULL);
    878           }
    879           if (MoreAttemptsAllowed()) {
    880             result = MakeAttempt();
    881           } else if (result.rv == ERR_DNS_MALFORMED_RESPONSE &&
    882                      !had_tcp_attempt_) {
    883             // For UDP only, ignore the response and wait until the last attempt
    884             // times out.
    885             return AttemptResult(ERR_IO_PENDING, NULL);
    886           } else {
    887             return AttemptResult(result.rv, NULL);
    888           }
    889           break;
    890       }
    891     }
    892     return result;
    893   }
    894 
    895   void OnTimeout() {
    896     if (callback_.is_null())
    897       return;
    898     DCHECK(!attempts_.empty());
    899     AttemptResult result = ProcessAttemptResult(
    900         AttemptResult(ERR_DNS_TIMED_OUT, attempts_.back()));
    901     if (result.rv != ERR_IO_PENDING)
    902       DoCallback(result);
    903   }
    904 
    905   scoped_refptr<DnsSession> session_;
    906   std::string hostname_;
    907   uint16 qtype_;
    908   // Cleared in DoCallback.
    909   DnsTransactionFactory::CallbackType callback_;
    910 
    911   BoundNetLog net_log_;
    912 
    913   // Search list of fully-qualified DNS names to query next (in DNS format).
    914   std::deque<std::string> qnames_;
    915   size_t qnames_initial_size_;
    916 
    917   // List of attempts for the current name.
    918   ScopedVector<DnsAttempt> attempts_;
    919   // Count of attempts, not reset when |attempts_| vector is cleared.
    920   int  attempts_count_;
    921   bool had_tcp_attempt_;
    922 
    923   // Index of the first server to try on each search query.
    924   int first_server_index_;
    925 
    926   base::OneShotTimer<DnsTransactionImpl> timer_;
    927 
    928   DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl);
    929 };
    930 
    931 // ----------------------------------------------------------------------------
    932 
    933 // Implementation of DnsTransactionFactory that returns instances of
    934 // DnsTransactionImpl.
    935 class DnsTransactionFactoryImpl : public DnsTransactionFactory {
    936  public:
    937   explicit DnsTransactionFactoryImpl(DnsSession* session) {
    938     session_ = session;
    939   }
    940 
    941   virtual scoped_ptr<DnsTransaction> CreateTransaction(
    942       const std::string& hostname,
    943       uint16 qtype,
    944       const CallbackType& callback,
    945       const BoundNetLog& net_log) OVERRIDE {
    946     return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(
    947         session_.get(), hostname, qtype, callback, net_log));
    948   }
    949 
    950  private:
    951   scoped_refptr<DnsSession> session_;
    952 };
    953 
    954 }  // namespace
    955 
    956 // static
    957 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
    958     DnsSession* session) {
    959   return scoped_ptr<DnsTransactionFactory>(
    960       new DnsTransactionFactoryImpl(session));
    961 }
    962 
    963 }  // namespace net
    964