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/big_endian.h"
     12 #include "base/bind.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/scoped_vector.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/message_loop/message_loop.h"
     18 #include "base/metrics/histogram.h"
     19 #include "base/rand_util.h"
     20 #include "base/stl_util.h"
     21 #include "base/strings/string_piece.h"
     22 #include "base/threading/non_thread_safe.h"
     23 #include "base/timer/timer.h"
     24 #include "base/values.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_LENGTH_COMPLETE,
    343     STATE_READ_RESPONSE,
    344     STATE_READ_RESPONSE_COMPLETE,
    345     STATE_NONE,
    346   };
    347 
    348   int DoLoop(int result) {
    349     CHECK_NE(STATE_NONE, next_state_);
    350     int rv = result;
    351     do {
    352       State state = next_state_;
    353       next_state_ = STATE_NONE;
    354       switch (state) {
    355         case STATE_CONNECT_COMPLETE:
    356           rv = DoConnectComplete(rv);
    357           break;
    358         case STATE_SEND_LENGTH:
    359           rv = DoSendLength(rv);
    360           break;
    361         case STATE_SEND_QUERY:
    362           rv = DoSendQuery(rv);
    363           break;
    364         case STATE_READ_LENGTH:
    365           rv = DoReadLength(rv);
    366           break;
    367         case STATE_READ_LENGTH_COMPLETE:
    368           rv = DoReadLengthComplete(rv);
    369           break;
    370         case STATE_READ_RESPONSE:
    371           rv = DoReadResponse(rv);
    372           break;
    373         case STATE_READ_RESPONSE_COMPLETE:
    374           rv = DoReadResponseComplete(rv);
    375           break;
    376         default:
    377           NOTREACHED();
    378           break;
    379       }
    380     } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    381 
    382     set_result(rv);
    383     if (rv == OK) {
    384       DCHECK_EQ(STATE_NONE, next_state_);
    385       DNS_HISTOGRAM("AsyncDNS.TCPAttemptSuccess",
    386                     base::TimeTicks::Now() - start_time_);
    387     } else if (rv != ERR_IO_PENDING) {
    388       DNS_HISTOGRAM("AsyncDNS.TCPAttemptFail",
    389                     base::TimeTicks::Now() - start_time_);
    390     }
    391     return rv;
    392   }
    393 
    394   int DoConnectComplete(int rv) {
    395     DCHECK_NE(ERR_IO_PENDING, rv);
    396     if (rv < 0)
    397       return rv;
    398 
    399     base::WriteBigEndian<uint16>(length_buffer_->data(),
    400                                  query_->io_buffer()->size());
    401     buffer_ =
    402         new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size());
    403     next_state_ = STATE_SEND_LENGTH;
    404     return OK;
    405   }
    406 
    407   int DoSendLength(int rv) {
    408     DCHECK_NE(ERR_IO_PENDING, rv);
    409     if (rv < 0)
    410       return rv;
    411 
    412     buffer_->DidConsume(rv);
    413     if (buffer_->BytesRemaining() > 0) {
    414       next_state_ = STATE_SEND_LENGTH;
    415       return socket_->Write(
    416           buffer_.get(),
    417           buffer_->BytesRemaining(),
    418           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    419     }
    420     buffer_ = new DrainableIOBuffer(query_->io_buffer(),
    421                                     query_->io_buffer()->size());
    422     next_state_ = STATE_SEND_QUERY;
    423     return OK;
    424   }
    425 
    426   int DoSendQuery(int rv) {
    427     DCHECK_NE(ERR_IO_PENDING, rv);
    428     if (rv < 0)
    429       return rv;
    430 
    431     buffer_->DidConsume(rv);
    432     if (buffer_->BytesRemaining() > 0) {
    433       next_state_ = STATE_SEND_QUERY;
    434       return socket_->Write(
    435           buffer_.get(),
    436           buffer_->BytesRemaining(),
    437           base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    438     }
    439     buffer_ =
    440         new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size());
    441     next_state_ = STATE_READ_LENGTH;
    442     return OK;
    443   }
    444 
    445   int DoReadLength(int rv) {
    446     DCHECK_EQ(OK, rv);
    447 
    448     next_state_ = STATE_READ_LENGTH_COMPLETE;
    449     return ReadIntoBuffer();
    450   }
    451 
    452   int DoReadLengthComplete(int rv) {
    453     DCHECK_NE(ERR_IO_PENDING, rv);
    454     if (rv < 0)
    455       return rv;
    456     if (rv == 0)
    457       return ERR_CONNECTION_CLOSED;
    458 
    459     buffer_->DidConsume(rv);
    460     if (buffer_->BytesRemaining() > 0) {
    461       next_state_ = STATE_READ_LENGTH;
    462       return OK;
    463     }
    464 
    465     base::ReadBigEndian<uint16>(length_buffer_->data(), &response_length_);
    466     // Check if advertised response is too short. (Optimization only.)
    467     if (response_length_ < query_->io_buffer()->size())
    468       return ERR_DNS_MALFORMED_RESPONSE;
    469     // Allocate more space so that DnsResponse::InitParse sanity check passes.
    470     response_.reset(new DnsResponse(response_length_ + 1));
    471     buffer_ = new DrainableIOBuffer(response_->io_buffer(), response_length_);
    472     next_state_ = STATE_READ_RESPONSE;
    473     return OK;
    474   }
    475 
    476   int DoReadResponse(int rv) {
    477     DCHECK_EQ(OK, rv);
    478 
    479     next_state_ = STATE_READ_RESPONSE_COMPLETE;
    480     return ReadIntoBuffer();
    481   }
    482 
    483   int DoReadResponseComplete(int rv) {
    484     DCHECK_NE(ERR_IO_PENDING, rv);
    485     if (rv < 0)
    486       return rv;
    487     if (rv == 0)
    488       return ERR_CONNECTION_CLOSED;
    489 
    490     buffer_->DidConsume(rv);
    491     if (buffer_->BytesRemaining() > 0) {
    492       next_state_ = STATE_READ_RESPONSE;
    493       return OK;
    494     }
    495 
    496     if (!response_->InitParse(buffer_->BytesConsumed(), *query_))
    497       return ERR_DNS_MALFORMED_RESPONSE;
    498     if (response_->flags() & dns_protocol::kFlagTC)
    499       return ERR_UNEXPECTED;
    500     // TODO(szym): Frankly, none of these are expected.
    501     if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
    502       return ERR_NAME_NOT_RESOLVED;
    503     if (response_->rcode() != dns_protocol::kRcodeNOERROR)
    504       return ERR_DNS_SERVER_FAILED;
    505 
    506     return OK;
    507   }
    508 
    509   void OnIOComplete(int rv) {
    510     rv = DoLoop(rv);
    511     if (rv != ERR_IO_PENDING)
    512       callback_.Run(rv);
    513   }
    514 
    515   int ReadIntoBuffer() {
    516     return socket_->Read(
    517         buffer_.get(),
    518         buffer_->BytesRemaining(),
    519         base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
    520   }
    521 
    522   State next_state_;
    523   base::TimeTicks start_time_;
    524 
    525   scoped_ptr<StreamSocket> socket_;
    526   scoped_ptr<DnsQuery> query_;
    527   scoped_refptr<IOBufferWithSize> length_buffer_;
    528   scoped_refptr<DrainableIOBuffer> buffer_;
    529 
    530   uint16 response_length_;
    531   scoped_ptr<DnsResponse> response_;
    532 
    533   CompletionCallback callback_;
    534 
    535   DISALLOW_COPY_AND_ASSIGN(DnsTCPAttempt);
    536 };
    537 
    538 // ----------------------------------------------------------------------------
    539 
    540 // Implements DnsTransaction. Configuration is supplied by DnsSession.
    541 // The suffix list is built according to the DnsConfig from the session.
    542 // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout.
    543 // The first server to attempt on each query is given by
    544 // DnsSession::NextFirstServerIndex, and the order is round-robin afterwards.
    545 // Each server is attempted DnsConfig::attempts times.
    546 class DnsTransactionImpl : public DnsTransaction,
    547                            public base::NonThreadSafe,
    548                            public base::SupportsWeakPtr<DnsTransactionImpl> {
    549  public:
    550   DnsTransactionImpl(DnsSession* session,
    551                      const std::string& hostname,
    552                      uint16 qtype,
    553                      const DnsTransactionFactory::CallbackType& callback,
    554                      const BoundNetLog& net_log)
    555     : session_(session),
    556       hostname_(hostname),
    557       qtype_(qtype),
    558       callback_(callback),
    559       net_log_(net_log),
    560       qnames_initial_size_(0),
    561       attempts_count_(0),
    562       had_tcp_attempt_(false),
    563       first_server_index_(0) {
    564     DCHECK(session_.get());
    565     DCHECK(!hostname_.empty());
    566     DCHECK(!callback_.is_null());
    567     DCHECK(!IsIPLiteral(hostname_));
    568   }
    569 
    570   virtual ~DnsTransactionImpl() {
    571     if (!callback_.is_null()) {
    572       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION,
    573                                         ERR_ABORTED);
    574     }  // otherwise logged in DoCallback or Start
    575   }
    576 
    577   virtual const std::string& GetHostname() const OVERRIDE {
    578     DCHECK(CalledOnValidThread());
    579     return hostname_;
    580   }
    581 
    582   virtual uint16 GetType() const OVERRIDE {
    583     DCHECK(CalledOnValidThread());
    584     return qtype_;
    585   }
    586 
    587   virtual void Start() OVERRIDE {
    588     DCHECK(!callback_.is_null());
    589     DCHECK(attempts_.empty());
    590     net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION,
    591                         base::Bind(&NetLogStartCallback, &hostname_, qtype_));
    592     AttemptResult result(PrepareSearch(), NULL);
    593     if (result.rv == OK) {
    594       qnames_initial_size_ = qnames_.size();
    595       if (qtype_ == dns_protocol::kTypeA)
    596         UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchStart", qnames_.size());
    597       result = ProcessAttemptResult(StartQuery());
    598     }
    599 
    600     // Must always return result asynchronously, to avoid reentrancy.
    601     if (result.rv != ERR_IO_PENDING) {
    602       base::MessageLoop::current()->PostTask(
    603           FROM_HERE,
    604           base::Bind(&DnsTransactionImpl::DoCallback, AsWeakPtr(), result));
    605     }
    606   }
    607 
    608  private:
    609   // Wrapper for the result of a DnsUDPAttempt.
    610   struct AttemptResult {
    611     AttemptResult(int rv, const DnsAttempt* attempt)
    612         : rv(rv), attempt(attempt) {}
    613 
    614     int rv;
    615     const DnsAttempt* attempt;
    616   };
    617 
    618   // Prepares |qnames_| according to the DnsConfig.
    619   int PrepareSearch() {
    620     const DnsConfig& config = session_->config();
    621 
    622     std::string labeled_hostname;
    623     if (!DNSDomainFromDot(hostname_, &labeled_hostname))
    624       return ERR_INVALID_ARGUMENT;
    625 
    626     if (hostname_[hostname_.size() - 1] == '.') {
    627       // It's a fully-qualified name, no suffix search.
    628       qnames_.push_back(labeled_hostname);
    629       return OK;
    630     }
    631 
    632     int ndots = CountLabels(labeled_hostname) - 1;
    633 
    634     if (ndots > 0 && !config.append_to_multi_label_name) {
    635       qnames_.push_back(labeled_hostname);
    636       return OK;
    637     }
    638 
    639     // Set true when |labeled_hostname| is put on the list.
    640     bool had_hostname = false;
    641 
    642     if (ndots >= config.ndots) {
    643       qnames_.push_back(labeled_hostname);
    644       had_hostname = true;
    645     }
    646 
    647     std::string qname;
    648     for (size_t i = 0; i < config.search.size(); ++i) {
    649       // Ignore invalid (too long) combinations.
    650       if (!DNSDomainFromDot(hostname_ + "." + config.search[i], &qname))
    651         continue;
    652       if (qname.size() == labeled_hostname.size()) {
    653         if (had_hostname)
    654           continue;
    655         had_hostname = true;
    656       }
    657       qnames_.push_back(qname);
    658     }
    659 
    660     if (ndots > 0 && !had_hostname)
    661       qnames_.push_back(labeled_hostname);
    662 
    663     return qnames_.empty() ? ERR_DNS_SEARCH_EMPTY : OK;
    664   }
    665 
    666   void DoCallback(AttemptResult result) {
    667     DCHECK(!callback_.is_null());
    668     DCHECK_NE(ERR_IO_PENDING, result.rv);
    669     const DnsResponse* response = result.attempt ?
    670         result.attempt->GetResponse() : NULL;
    671     CHECK(result.rv != OK || response != NULL);
    672 
    673     timer_.Stop();
    674     RecordLostPacketsIfAny();
    675     if (result.rv == OK)
    676       UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountSuccess", attempts_count_);
    677     else
    678       UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountFail", attempts_count_);
    679 
    680     if (response && qtype_ == dns_protocol::kTypeA) {
    681       UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchRemain", qnames_.size());
    682       UMA_HISTOGRAM_COUNTS("AsyncDNS.SuffixSearchDone",
    683                            qnames_initial_size_ - qnames_.size());
    684     }
    685 
    686     DnsTransactionFactory::CallbackType callback = callback_;
    687     callback_.Reset();
    688 
    689     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, result.rv);
    690     callback.Run(this, result.rv, response);
    691   }
    692 
    693   // Makes another attempt at the current name, |qnames_.front()|, using the
    694   // next nameserver.
    695   AttemptResult MakeAttempt() {
    696     unsigned attempt_number = attempts_.size();
    697 
    698     uint16 id = session_->NextQueryId();
    699     scoped_ptr<DnsQuery> query;
    700     if (attempts_.empty()) {
    701       query.reset(new DnsQuery(id, qnames_.front(), qtype_));
    702     } else {
    703       query.reset(attempts_[0]->GetQuery()->CloneWithNewId(id));
    704     }
    705 
    706     const DnsConfig& config = session_->config();
    707 
    708     unsigned server_index =
    709         (first_server_index_ + attempt_number) % config.nameservers.size();
    710     // Skip over known failed servers.
    711     server_index = session_->NextGoodServerIndex(server_index);
    712 
    713     scoped_ptr<DnsSession::SocketLease> lease =
    714         session_->AllocateSocket(server_index, net_log_.source());
    715 
    716     bool got_socket = !!lease.get();
    717 
    718     DnsUDPAttempt* attempt =
    719         new DnsUDPAttempt(server_index, lease.Pass(), query.Pass());
    720 
    721     attempts_.push_back(attempt);
    722     ++attempts_count_;
    723 
    724     if (!got_socket)
    725       return AttemptResult(ERR_CONNECTION_REFUSED, NULL);
    726 
    727     net_log_.AddEvent(
    728         NetLog::TYPE_DNS_TRANSACTION_ATTEMPT,
    729         attempt->GetSocketNetLog().source().ToEventParametersCallback());
    730 
    731     int rv = attempt->Start(
    732         base::Bind(&DnsTransactionImpl::OnUdpAttemptComplete,
    733                    base::Unretained(this), attempt_number,
    734                    base::TimeTicks::Now()));
    735     if (rv == ERR_IO_PENDING) {
    736       base::TimeDelta timeout = session_->NextTimeout(server_index,
    737                                                       attempt_number);
    738       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout);
    739     }
    740     return AttemptResult(rv, attempt);
    741   }
    742 
    743   AttemptResult MakeTCPAttempt(const DnsAttempt* previous_attempt) {
    744     DCHECK(previous_attempt);
    745     DCHECK(!had_tcp_attempt_);
    746 
    747     unsigned server_index = previous_attempt->server_index();
    748 
    749     scoped_ptr<StreamSocket> socket(
    750         session_->CreateTCPSocket(server_index, net_log_.source()));
    751 
    752     // TODO(szym): Reuse the same id to help the server?
    753     uint16 id = session_->NextQueryId();
    754     scoped_ptr<DnsQuery> query(
    755         previous_attempt->GetQuery()->CloneWithNewId(id));
    756 
    757     RecordLostPacketsIfAny();
    758     // Cancel all other attempts, no point waiting on them.
    759     attempts_.clear();
    760 
    761     unsigned attempt_number = attempts_.size();
    762 
    763     DnsTCPAttempt* attempt = new DnsTCPAttempt(server_index, socket.Pass(),
    764                                                query.Pass());
    765 
    766     attempts_.push_back(attempt);
    767     ++attempts_count_;
    768     had_tcp_attempt_ = true;
    769 
    770     net_log_.AddEvent(
    771         NetLog::TYPE_DNS_TRANSACTION_TCP_ATTEMPT,
    772         attempt->GetSocketNetLog().source().ToEventParametersCallback());
    773 
    774     int rv = attempt->Start(base::Bind(&DnsTransactionImpl::OnAttemptComplete,
    775                                        base::Unretained(this),
    776                                        attempt_number));
    777     if (rv == ERR_IO_PENDING) {
    778       // Custom timeout for TCP attempt.
    779       base::TimeDelta timeout = timer_.GetCurrentDelay() * 2;
    780       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout);
    781     }
    782     return AttemptResult(rv, attempt);
    783   }
    784 
    785   // Begins query for the current name. Makes the first attempt.
    786   AttemptResult StartQuery() {
    787     std::string dotted_qname = DNSDomainToString(qnames_.front());
    788     net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    789                         NetLog::StringCallback("qname", &dotted_qname));
    790 
    791     first_server_index_ = session_->NextFirstServerIndex();
    792     RecordLostPacketsIfAny();
    793     attempts_.clear();
    794     had_tcp_attempt_ = false;
    795     return MakeAttempt();
    796   }
    797 
    798   void OnUdpAttemptComplete(unsigned attempt_number,
    799                             base::TimeTicks start,
    800                             int rv) {
    801     DCHECK_LT(attempt_number, attempts_.size());
    802     const DnsAttempt* attempt = attempts_[attempt_number];
    803     if (attempt->GetResponse()) {
    804       session_->RecordRTT(attempt->server_index(),
    805                           base::TimeTicks::Now() - start);
    806     }
    807     OnAttemptComplete(attempt_number, rv);
    808   }
    809 
    810   void OnAttemptComplete(unsigned attempt_number, int rv) {
    811     if (callback_.is_null())
    812       return;
    813     DCHECK_LT(attempt_number, attempts_.size());
    814     const DnsAttempt* attempt = attempts_[attempt_number];
    815     AttemptResult result = ProcessAttemptResult(AttemptResult(rv, attempt));
    816     if (result.rv != ERR_IO_PENDING)
    817       DoCallback(result);
    818   }
    819 
    820   // Record packet loss for any incomplete attempts.
    821   void RecordLostPacketsIfAny() {
    822     // Loop through attempts until we find first that is completed
    823     size_t first_completed = 0;
    824     for (first_completed = 0; first_completed < attempts_.size();
    825         ++first_completed) {
    826       if (attempts_[first_completed]->is_completed())
    827         break;
    828     }
    829     // If there were no completed attempts, then we must be offline, so don't
    830     // record any attempts as lost packets.
    831     if (first_completed == attempts_.size())
    832       return;
    833 
    834     size_t num_servers = session_->config().nameservers.size();
    835     std::vector<int> server_attempts(num_servers);
    836     for (size_t i = 0; i < first_completed; ++i) {
    837       unsigned server_index = attempts_[i]->server_index();
    838       int server_attempt = server_attempts[server_index]++;
    839       // Don't record lost packet unless attempt is in pending state.
    840       if (!attempts_[i]->is_pending())
    841         continue;
    842       session_->RecordLostPacket(server_index, server_attempt);
    843     }
    844   }
    845 
    846   void LogResponse(const DnsAttempt* attempt) {
    847     if (attempt && attempt->GetResponse()) {
    848       net_log_.AddEvent(
    849           NetLog::TYPE_DNS_TRANSACTION_RESPONSE,
    850           base::Bind(&DnsAttempt::NetLogResponseCallback,
    851                      base::Unretained(attempt)));
    852     }
    853   }
    854 
    855   bool MoreAttemptsAllowed() const {
    856     if (had_tcp_attempt_)
    857       return false;
    858     const DnsConfig& config = session_->config();
    859     return attempts_.size() < config.attempts * config.nameservers.size();
    860   }
    861 
    862   // Resolves the result of a DnsAttempt until a terminal result is reached
    863   // or it will complete asynchronously (ERR_IO_PENDING).
    864   AttemptResult ProcessAttemptResult(AttemptResult result) {
    865     while (result.rv != ERR_IO_PENDING) {
    866       LogResponse(result.attempt);
    867 
    868       switch (result.rv) {
    869         case OK:
    870           session_->RecordServerSuccess(result.attempt->server_index());
    871           net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    872                                             result.rv);
    873           DCHECK(result.attempt);
    874           DCHECK(result.attempt->GetResponse());
    875           return result;
    876         case ERR_NAME_NOT_RESOLVED:
    877           session_->RecordServerSuccess(result.attempt->server_index());
    878           net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION_QUERY,
    879                                             result.rv);
    880           // Try next suffix.
    881           qnames_.pop_front();
    882           if (qnames_.empty()) {
    883             return AttemptResult(ERR_NAME_NOT_RESOLVED, NULL);
    884           } else {
    885             result = StartQuery();
    886           }
    887           break;
    888         case ERR_CONNECTION_REFUSED:
    889         case ERR_DNS_TIMED_OUT:
    890           if (result.attempt)
    891             session_->RecordServerFailure(result.attempt->server_index());
    892           if (MoreAttemptsAllowed()) {
    893             result = MakeAttempt();
    894           } else {
    895             return result;
    896           }
    897           break;
    898         case ERR_DNS_SERVER_REQUIRES_TCP:
    899           result = MakeTCPAttempt(result.attempt);
    900           break;
    901         default:
    902           // Server failure.
    903           DCHECK(result.attempt);
    904           if (result.attempt != attempts_.back()) {
    905             // This attempt already timed out. Ignore it.
    906             session_->RecordServerFailure(result.attempt->server_index());
    907             return AttemptResult(ERR_IO_PENDING, NULL);
    908           }
    909           if (MoreAttemptsAllowed()) {
    910             result = MakeAttempt();
    911           } else if (result.rv == ERR_DNS_MALFORMED_RESPONSE &&
    912                      !had_tcp_attempt_) {
    913             // For UDP only, ignore the response and wait until the last attempt
    914             // times out.
    915             return AttemptResult(ERR_IO_PENDING, NULL);
    916           } else {
    917             return AttemptResult(result.rv, NULL);
    918           }
    919           break;
    920       }
    921     }
    922     return result;
    923   }
    924 
    925   void OnTimeout() {
    926     if (callback_.is_null())
    927       return;
    928     DCHECK(!attempts_.empty());
    929     AttemptResult result = ProcessAttemptResult(
    930         AttemptResult(ERR_DNS_TIMED_OUT, attempts_.back()));
    931     if (result.rv != ERR_IO_PENDING)
    932       DoCallback(result);
    933   }
    934 
    935   scoped_refptr<DnsSession> session_;
    936   std::string hostname_;
    937   uint16 qtype_;
    938   // Cleared in DoCallback.
    939   DnsTransactionFactory::CallbackType callback_;
    940 
    941   BoundNetLog net_log_;
    942 
    943   // Search list of fully-qualified DNS names to query next (in DNS format).
    944   std::deque<std::string> qnames_;
    945   size_t qnames_initial_size_;
    946 
    947   // List of attempts for the current name.
    948   ScopedVector<DnsAttempt> attempts_;
    949   // Count of attempts, not reset when |attempts_| vector is cleared.
    950   int  attempts_count_;
    951   bool had_tcp_attempt_;
    952 
    953   // Index of the first server to try on each search query.
    954   int first_server_index_;
    955 
    956   base::OneShotTimer<DnsTransactionImpl> timer_;
    957 
    958   DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl);
    959 };
    960 
    961 // ----------------------------------------------------------------------------
    962 
    963 // Implementation of DnsTransactionFactory that returns instances of
    964 // DnsTransactionImpl.
    965 class DnsTransactionFactoryImpl : public DnsTransactionFactory {
    966  public:
    967   explicit DnsTransactionFactoryImpl(DnsSession* session) {
    968     session_ = session;
    969   }
    970 
    971   virtual scoped_ptr<DnsTransaction> CreateTransaction(
    972       const std::string& hostname,
    973       uint16 qtype,
    974       const CallbackType& callback,
    975       const BoundNetLog& net_log) OVERRIDE {
    976     return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(
    977         session_.get(), hostname, qtype, callback, net_log));
    978   }
    979 
    980  private:
    981   scoped_refptr<DnsSession> session_;
    982 };
    983 
    984 }  // namespace
    985 
    986 // static
    987 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
    988     DnsSession* session) {
    989   return scoped_ptr<DnsTransactionFactory>(
    990       new DnsTransactionFactoryImpl(session));
    991 }
    992 
    993 }  // namespace net
    994