Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1228)

Unified Diff: net/dns/dns_transaction.cc

Issue 9190031: DnsClient refactoring + features (timeout, suffix search, server rotation). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Delinted. Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/dns/dns_transaction.h ('k') | net/dns/dns_transaction_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/dns/dns_transaction.cc
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index 6d711b4a5a97cbcd3fe4d3b88cf1192a962a3177..8222863690aa38006bd6f7be416ea80d699f1b20 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -1,14 +1,29 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/dns/dns_transaction.h"
+#include <deque>
+#include <string>
+#include <vector>
+
#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
#include "base/rand_util.h"
-#include "base/values.h"
+#include "base/stl_util.h"
+#include "base/string_piece.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/timer.h"
+#include "net/base/completion_callback.h"
+#include "net/base/dns_util.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_response.h"
@@ -20,259 +35,497 @@ namespace net {
namespace {
-class DnsTransactionStartParameters : public NetLog::EventParameters {
+// Count labels in the fully-qualified name in DNS format.
+int CountLabels(const std::string& name) {
+ size_t count = 0;
+ for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1)
+ ++count;
+ return count;
+}
+
+bool IsIPLiteral(const std::string& hostname) {
+ IPAddressNumber ip;
+ return ParseIPLiteralToNumber(hostname, &ip);
+}
+
+class StartParameters : public NetLog::EventParameters {
public:
- DnsTransactionStartParameters(const IPEndPoint& dns_server,
- const base::StringPiece& qname,
- uint16 qtype,
- const NetLog::Source& source)
- : dns_server_(dns_server),
- qname_(qname.data(), qname.length()),
- qtype_(qtype),
- source_(source) {}
-
- virtual Value* ToValue() const {
+ StartParameters(const std::string& hostname,
+ uint16 qtype,
+ const NetLog::Source& source)
+ : hostname_(hostname), qtype_(qtype), source_(source) {}
+
+ virtual Value* ToValue() const OVERRIDE {
DictionaryValue* dict = new DictionaryValue();
- dict->SetString("dns_server", dns_server_.ToString());
- dict->SetString("hostname", qname_);
+ dict->SetString("hostname", hostname_);
dict->SetInteger("query_type", qtype_);
- if (source_.is_valid())
- dict->Set("source_dependency", source_.ToValue());
+ dict->Set("source_dependency", source_.ToValue());
return dict;
}
private:
- IPEndPoint dns_server_;
- std::string qname_;
- uint16 qtype_;
+ const std::string hostname_;
+ const uint16 qtype_;
const NetLog::Source source_;
};
-class DnsTransactionFinishParameters : public NetLog::EventParameters {
+class ResponseParameters : public NetLog::EventParameters {
public:
- // TODO(szym): add rcode ?
- DnsTransactionFinishParameters(int net_error, int answer_count)
- : net_error_(net_error), answer_count_(answer_count) {}
+ ResponseParameters(int rcode, int answer_count, const NetLog::Source& source)
+ : rcode_(rcode), answer_count_(answer_count), source_(source) {}
- virtual Value* ToValue() const {
+ virtual Value* ToValue() const OVERRIDE {
DictionaryValue* dict = new DictionaryValue();
- if (net_error_)
- dict->SetInteger("net_error", net_error_);
+ dict->SetInteger("rcode", rcode_);
dict->SetInteger("answer_count", answer_count_);
+ dict->Set("socket_source", source_.ToValue());
return dict;
}
private:
- const int net_error_;
+ const int rcode_;
const int answer_count_;
+ const NetLog::Source source_;
};
-class DnsTransactionRetryParameters : public NetLog::EventParameters {
+// ----------------------------------------------------------------------------
+
+// A single asynchronous DNS exchange over UDP, which consists of sending out a
+// DNS query, waiting for a response, and returning the response that it
+// matches. Logging is done in the socket and in the outer DnsTransaction.
+class DnsUDPAttempt {
public:
- DnsTransactionRetryParameters(int attempt_number,
- const NetLog::Source& source)
- : attempt_number_(attempt_number), source_(source) {}
+ DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket,
+ const IPEndPoint& server,
+ scoped_ptr<DnsQuery> query,
+ const CompletionCallback& callback)
+ : next_state_(STATE_NONE),
+ socket_(socket.Pass()),
+ server_(server),
+ query_(query.Pass()),
+ callback_(callback) {
+ }
- virtual Value* ToValue() const {
- DictionaryValue* dict = new DictionaryValue();
- dict->SetInteger("attempt_number", attempt_number_);
- dict->Set("source_dependency", source_.ToValue());
- return dict;
+ // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously
+ // and calls |callback| upon completion.
+ int Start() {
+ DCHECK_EQ(STATE_NONE, next_state_);
+ next_state_ = STATE_CONNECT;
+ return DoLoop(OK);
+ }
+
+ const DnsQuery* query() const {
+ return query_.get();
+ }
+
+ const DatagramClientSocket* socket() const {
+ return socket_.get();
+ }
+
+ // Returns the response or NULL if has not received a matching response from
+ // the server.
+ const DnsResponse* response() const {
+ const DnsResponse* resp = response_.get();
+ return (resp != NULL && resp->IsValid()) ? resp : NULL;
}
private:
- const int attempt_number_;
- const NetLog::Source source_;
-};
+ enum State {
+ STATE_CONNECT,
+ STATE_SEND_QUERY,
+ STATE_SEND_QUERY_COMPLETE,
+ STATE_READ_RESPONSE,
+ STATE_READ_RESPONSE_COMPLETE,
+ STATE_NONE,
+ };
+
+ int DoLoop(int result) {
+ DCHECK_NE(STATE_NONE, next_state_);
+ int rv = result;
+ do {
+ State state = next_state_;
+ next_state_ = STATE_NONE;
+ switch (state) {
+ case STATE_CONNECT:
+ rv = DoConnect();
+ break;
+ case STATE_SEND_QUERY:
+ rv = DoSendQuery();
+ break;
+ case STATE_SEND_QUERY_COMPLETE:
+ rv = DoSendQueryComplete(rv);
+ break;
+ case STATE_READ_RESPONSE:
+ rv = DoReadResponse();
+ break;
+ case STATE_READ_RESPONSE_COMPLETE:
+ rv = DoReadResponseComplete(rv);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
-} // namespace
+ return rv;
+ }
+
+ int DoConnect() {
+ next_state_ = STATE_SEND_QUERY;
+ return socket_->Connect(server_);
+ }
+
+ int DoSendQuery() {
+ next_state_ = STATE_SEND_QUERY_COMPLETE;
+ return socket_->Write(query_->io_buffer(),
+ query_->io_buffer()->size(),
+ base::Bind(&DnsUDPAttempt::OnIOComplete,
+ base::Unretained(this)));
+ }
+
+ int DoSendQueryComplete(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (rv < 0)
+ return rv;
+
+ // Writing to UDP should not result in a partial datagram.
+ if (rv != query_->io_buffer()->size())
+ return ERR_MSG_TOO_BIG;
+ next_state_ = STATE_READ_RESPONSE;
+ return OK;
+ }
+
+ int DoReadResponse() {
+ next_state_ = STATE_READ_RESPONSE_COMPLETE;
+ response_.reset(new DnsResponse());
+ return socket_->Read(response_->io_buffer(),
+ response_->io_buffer()->size(),
+ base::Bind(&DnsUDPAttempt::OnIOComplete,
+ base::Unretained(this)));
+ }
+
+ int DoReadResponseComplete(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (rv < 0)
+ return rv;
+
+ DCHECK(rv);
+ if (!response_->InitParse(rv, *query_))
+ return ERR_DNS_MALFORMED_RESPONSE;
+ if (response_->flags() & dns_protocol::kFlagTC)
+ return ERR_DNS_SERVER_REQUIRES_TCP;
+ if (response_->rcode() != dns_protocol::kRcodeNOERROR &&
+ response_->rcode() != dns_protocol::kRcodeNXDOMAIN) {
+ return ERR_DNS_SERVER_FAILED;
+ }
+ if (response_->answer_count() == 0)
+ return ERR_NAME_NOT_RESOLVED;
+
+ return OK;
+ }
+
+ void OnIOComplete(int rv) {
+ rv = DoLoop(rv);
+ if (rv != ERR_IO_PENDING)
+ callback_.Run(rv);
+ }
+
+ State next_state_;
+
+ scoped_ptr<DatagramClientSocket> socket_;
+ IPEndPoint server_;
+ scoped_ptr<DnsQuery> query_;
+
+ scoped_ptr<DnsResponse> response_;
+
+ CompletionCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt);
+};
+
+// ----------------------------------------------------------------------------
-DnsTransaction::DnsTransaction(DnsSession* session,
- const base::StringPiece& qname,
- uint16 qtype,
- const ResultCallback& callback,
- const BoundNetLog& source_net_log)
+// Implements DnsTransaction. Configuration is supplied by DnsSession.
+// The suffix list is built according to the DnsConfig from the session.
+// The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout.
+// The first server to attempt on each query is given by
+// DnsSession::NextFirstServerIndex, and the order is round-robin afterwards.
+// Each server is attempted DnsConfig::attempts times.
+class DnsTransactionImpl : public DnsTransaction, public base::NonThreadSafe {
+ public:
+ DnsTransactionImpl(DnsSession* session,
+ const std::string& hostname,
+ uint16 qtype,
+ const DnsTransactionFactory::CallbackType& callback,
+ const BoundNetLog& source_net_log)
: session_(session),
- dns_server_(session->NextServer()),
- query_(new DnsQuery(session->NextId(), qname, qtype)),
+ hostname_(hostname),
+ qtype_(qtype),
callback_(callback),
- attempts_(0),
- next_state_(STATE_NONE),
net_log_(BoundNetLog::Make(session->net_log(),
- NetLog::SOURCE_DNS_TRANSACTION)) {
- net_log_.BeginEvent(
- NetLog::TYPE_DNS_TRANSACTION,
- make_scoped_refptr(
- new DnsTransactionStartParameters(dns_server_,
- qname,
- qtype,
- source_net_log.source())));
-}
+ NetLog::SOURCE_DNS_TRANSACTION)),
+ first_server_index_(0) {
+ DCHECK(session_);
+ DCHECK(!hostname_.empty());
+ DCHECK(!callback_.is_null());
-DnsTransaction::~DnsTransaction() {}
+ DCHECK(!IsIPLiteral(hostname_));
-int DnsTransaction::Start() {
- DCHECK_EQ(STATE_NONE, next_state_);
- next_state_ = STATE_CONNECT;
- return DoLoop(OK);
-}
+ net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, make_scoped_refptr(
+ new StartParameters(hostname_, qtype_, source_net_log.source())));
+ }
-int DnsTransaction::DoLoop(int result) {
- DCHECK_NE(STATE_NONE, next_state_);
- int rv = result;
- do {
- State state = next_state_;
- next_state_ = STATE_NONE;
- switch (state) {
- case STATE_CONNECT:
- rv = DoConnect();
- break;
- case STATE_CONNECT_COMPLETE:
- rv = DoConnectComplete(rv);
- break;
- case STATE_SEND_QUERY:
- rv = DoSendQuery();
- break;
- case STATE_SEND_QUERY_COMPLETE:
- rv = DoSendQueryComplete(rv);
- break;
- case STATE_READ_RESPONSE:
- rv = DoReadResponse();
- break;
- case STATE_READ_RESPONSE_COMPLETE:
- rv = DoReadResponseComplete(rv);
- break;
- default:
- NOTREACHED();
- break;
+ virtual ~DnsTransactionImpl() {
+ STLDeleteElements(&attempts_);
+ if (!callback_.is_null()) {
+ net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION,
+ ERR_ABORTED);
}
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
+ }
- return rv;
-}
+ virtual const std::string& GetHostname() const OVERRIDE {
+ DCHECK(CalledOnValidThread());
+ return hostname_;
+ }
-void DnsTransaction::DoCallback(int result) {
- DCHECK_NE(result, ERR_IO_PENDING);
- int answer_count = (result == OK) ? response()->answer_count() : 0;
- net_log_.EndEvent(
- NetLog::TYPE_DNS_TRANSACTION,
- make_scoped_refptr(
- new DnsTransactionFinishParameters(result, answer_count)));
- callback_.Run(this, result);
-}
+ virtual uint16 GetType() const OVERRIDE {
+ DCHECK(CalledOnValidThread());
+ return qtype_;
+ }
-void DnsTransaction::OnIOComplete(int result) {
- int rv = DoLoop(result);
- if (rv != ERR_IO_PENDING)
- DoCallback(rv);
-}
+ virtual int Start() OVERRIDE {
+ int rv = PrepareSearch();
+ if (rv == OK)
+ rv = StartQuery();
+ DCHECK_NE(OK, rv);
+ return rv;
+ }
-int DnsTransaction::DoConnect() {
- next_state_ = STATE_CONNECT_COMPLETE;
-
- StartTimer(session_->NextTimeout(attempts_));
- ++attempts_;
-
- // TODO(szym): keep all sockets around in case the server responds
- // after its timeout; state machine will need to change to handle that.
- // The current plan is to move socket management out to DnsSession.
- // Hence also move retransmissions to DnsClient::Request.
- socket_.reset(session_->socket_factory()->CreateDatagramClientSocket(
- DatagramSocket::RANDOM_BIND,
- base::Bind(&base::RandInt),
- net_log_.net_log(),
- net_log_.source()));
-
- net_log_.AddEvent(
- NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED,
- make_scoped_refptr(
- new DnsTransactionRetryParameters(attempts_,
- socket_->NetLog().source())));
-
- return socket_->Connect(dns_server_);
-}
+ private:
+ // Prepares |qnames_| according to the DnsConfig.
+ int PrepareSearch() {
+ const DnsConfig& config = session_->config();
+
+ std::string labelled_hostname;
+ if (!DNSDomainFromDot(hostname_, &labelled_hostname))
+ return ERR_INVALID_ARGUMENT;
+
+ if (hostname_[hostname_.size() - 1] == '.') {
+ // It's a fully-qualified name, no suffix search.
+ qnames_.push_back(labelled_hostname);
+ return OK;
+ }
-int DnsTransaction::DoConnectComplete(int rv) {
- if (rv < 0)
- return rv;
- next_state_ = STATE_SEND_QUERY;
- return OK;
-}
+ // Set true when |labelled_hostname| is put on the list.
+ bool had_hostname = false;
-int DnsTransaction::DoSendQuery() {
- next_state_ = STATE_SEND_QUERY_COMPLETE;
- return socket_->Write(query_->io_buffer(),
- query_->io_buffer()->size(),
- base::Bind(&DnsTransaction::OnIOComplete,
- base::Unretained(this)));
-}
+ int ndots = CountLabels(labelled_hostname) - 1;
+ if (ndots >= config.ndots) {
+ qnames_.push_back(labelled_hostname);
+ had_hostname = true;
+ }
-int DnsTransaction::DoSendQueryComplete(int rv) {
- if (rv < 0)
- return rv;
+ std::string qname;
+ for (size_t i = 0; i < config.search.size(); ++i) {
+ // Ignore invalid (too long) combinations.
+ if (!DNSDomainFromDot(hostname_ + "." + config.search[i], &qname))
+ continue;
+ if (qname.size() == labelled_hostname.size()) {
+ if (had_hostname)
+ continue;
+ had_hostname = true;
+ }
+ qnames_.push_back(qname);
+ }
- // Writing to UDP should not result in a partial datagram.
- if (rv != query_->io_buffer()->size())
- return ERR_MSG_TOO_BIG;
+ if (!had_hostname)
+ qnames_.push_back(labelled_hostname);
- next_state_ = STATE_READ_RESPONSE;
- return OK;
-}
+ return OK;
+ }
-int DnsTransaction::DoReadResponse() {
- next_state_ = STATE_READ_RESPONSE_COMPLETE;
- response_.reset(new DnsResponse());
- return socket_->Read(response_->io_buffer(),
- response_->io_buffer()->size(),
- base::Bind(&DnsTransaction::OnIOComplete,
- base::Unretained(this)));
-}
+ void DoCallback(int rv, const DnsUDPAttempt* successful_attempt) {
+ if (callback_.is_null())
+ return;
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ DCHECK(rv != OK || successful_attempt != NULL);
+
+ DnsTransactionFactory::CallbackType callback = callback_;
+ callback_.Reset();
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, rv);
+ callback.Run(this,
+ rv,
+ successful_attempt ? successful_attempt->response() : NULL);
+ }
-int DnsTransaction::DoReadResponseComplete(int rv) {
- DCHECK_NE(ERR_IO_PENDING, rv);
- RevokeTimer();
- if (rv < 0)
- return rv;
+ // Makes another attempt at the current name, |qnames_.front()|, using the
+ // next nameserver.
+ int MakeAttempt() {
+ unsigned attempt_number = attempts_.size();
+
+ scoped_ptr<DatagramClientSocket> socket(
+ session_->socket_factory()->CreateDatagramClientSocket(
+ DatagramSocket::RANDOM_BIND,
+ base::Bind(&base::RandInt),
+ net_log_.net_log(),
+ net_log_.source()));
+
+ uint16 id = session_->NextQueryId();
+ scoped_ptr<DnsQuery> query;
+ if (attempts_.empty()) {
+ query.reset(new DnsQuery(id, qnames_.front(), qtype_));
+ } else {
+ query.reset(attempts_[0]->query()->CloneWithNewId(id));
+ }
+
+ net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, make_scoped_refptr(
+ new NetLogSourceParameter("socket_source", socket->NetLog().source())));
+
+ const DnsConfig& config = session_->config();
+
+ unsigned server_index = first_server_index_ +
+ (attempt_number % config.nameservers.size());
+
+ DnsUDPAttempt* attempt = new DnsUDPAttempt(
+ socket.Pass(),
+ config.nameservers[server_index],
+ query.Pass(),
+ base::Bind(&DnsTransactionImpl::OnAttemptComplete,
+ base::Unretained(this),
+ attempt_number));
- DCHECK(rv);
- if (!response_->InitParse(rv, *query_))
- return ERR_DNS_MALFORMED_RESPONSE;
- // TODO(szym): define this flag value in dns_protocol
- if (response_->flags1() & 2)
- return ERR_DNS_SERVER_REQUIRES_TCP;
- // TODO(szym): move this handling out of DnsTransaction?
- if (response_->rcode() != dns_protocol::kRcodeNOERROR &&
- response_->rcode() != dns_protocol::kRcodeNXDOMAIN) {
- return ERR_DNS_SERVER_FAILED;
+ base::TimeDelta timeout = session_->NextTimeout(attempt_number);
+ timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout);
+ attempts_.push_back(attempt);
+ return attempt->Start();
}
- // TODO(szym): add ERR_DNS_RR_NOT_FOUND?
- if (response_->answer_count() == 0)
- return ERR_NAME_NOT_RESOLVED;
- return OK;
-}
+ // Begins query for the current name. Makes the first attempt.
+ int StartQuery() {
+ std::string dotted_qname = DNSDomainToString(qnames_.front());
+ net_log_.BeginEvent(
+ NetLog::TYPE_DNS_TRANSACTION_QUERY,
+ make_scoped_refptr(new NetLogStringParameter("qname", dotted_qname)));
-void DnsTransaction::StartTimer(base::TimeDelta delay) {
- timer_.Start(FROM_HERE, delay, this, &DnsTransaction::OnTimeout);
-}
+ first_server_index_ = session_->NextFirstServerIndex();
-void DnsTransaction::RevokeTimer() {
- timer_.Stop();
-}
+ STLDeleteElements(&attempts_);
+ return MakeAttempt();
+ }
+
+ void OnAttemptComplete(unsigned attempt_number, int rv) {
+ DCHECK_LT(attempt_number, attempts_.size());
+ timer_.Stop();
+
+ const DnsUDPAttempt* attempt = attempts_[attempt_number];
+
+ if (attempt->response()) {
+ net_log_.AddEvent(
+ NetLog::TYPE_DNS_TRANSACTION_RESPONSE,
+ make_scoped_refptr(
+ new ResponseParameters(attempt->response()->rcode(),
+ attempt->response()->answer_count(),
+ attempt->socket()->NetLog().source())));
+ }
+
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION_QUERY, rv);
+
+ switch (rv) {
+ case ERR_NAME_NOT_RESOLVED:
+ // Try next suffix.
+ qnames_.pop_front();
+ if (qnames_.empty())
+ rv = ERR_NAME_NOT_RESOLVED;
+ else
+ rv = StartQuery();
+ break;
+ case OK:
+ DoCallback(rv, attempt);
+ return;
+ default:
+ // TODO(szym): Some nameservers could fail so try the next one.
+ const DnsConfig& config = session_->config();
+ if (attempts_.size() < config.attempts * config.nameservers.size()) {
+ rv = MakeAttempt();
+ } else {
+ // TODO(szym): Should this be different than the timeout case?
+ rv = ERR_DNS_SERVER_FAILED;
+ }
+ break;
+ }
+ if (rv != ERR_IO_PENDING)
+ DoCallback(rv, NULL);
+ }
-void DnsTransaction::OnTimeout() {
- DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE ||
- next_state_ == STATE_READ_RESPONSE_COMPLETE);
- if (attempts_ == session_->config().attempts) {
- DoCallback(ERR_DNS_TIMED_OUT);
- return;
+ void OnTimeout() {
+ const DnsConfig& config = session_->config();
+ if (attempts_.size() == config.attempts * config.nameservers.size()) {
+ DoCallback(ERR_DNS_TIMED_OUT, NULL);
+ return;
+ }
+ int rv = MakeAttempt();
+ if (rv != ERR_IO_PENDING)
+ DoCallback(rv, NULL);
}
- next_state_ = STATE_CONNECT;
- query_.reset(query_->CloneWithNewId(session_->NextId()));
- int rv = DoLoop(OK);
- if (rv != ERR_IO_PENDING)
- DoCallback(rv);
+
+ scoped_refptr<DnsSession> session_;
+ std::string hostname_;
+ uint16 qtype_;
+ // Set to null once the transaction completes.
+ DnsTransactionFactory::CallbackType callback_;
+
+ BoundNetLog net_log_;
+
+ // Search list of fully-qualified DNS names to query next (in DNS format).
+ std::deque<std::string> qnames_;
+
+ // List of attempts for the current name.
+ std::vector<DnsUDPAttempt*> attempts_;
+
+ // Index of the first server to try on each search query.
+ int first_server_index_;
+
+ base::OneShotTimer<DnsTransactionImpl> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl);
+};
+
+// ----------------------------------------------------------------------------
+
+// Implementation of DnsTransactionFactory that returns instances of
+// DnsTransactionImpl.
+class DnsTransactionFactoryImpl : public DnsTransactionFactory {
+ public:
+ explicit DnsTransactionFactoryImpl(DnsSession* session) {
+ session_ = session;
+ }
+
+ virtual scoped_ptr<DnsTransaction> CreateTransaction(
+ const std::string& hostname,
+ uint16 qtype,
+ const CallbackType& callback,
+ const BoundNetLog& source_net_log) OVERRIDE {
+ return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(session_,
+ hostname,
+ qtype,
+ callback,
+ source_net_log));
+ }
+
+ private:
+ scoped_refptr<DnsSession> session_;
+};
+
+} // namespace
+
+// static
+scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
+ DnsSession* session) {
+ return scoped_ptr<DnsTransactionFactory>(
+ new DnsTransactionFactoryImpl(session));
}
} // namespace net
+
« no previous file with comments | « net/dns/dns_transaction.h ('k') | net/dns/dns_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698