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

Side by Side Diff: net/dns/dns_transaction.cc

Issue 8762001: Isolates generic DnsClient from AsyncHostResolver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_transaction.h" 5 #include "net/dns/dns_transaction.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "net/base/dns_util.h"
11 #include "net/base/io_buffer.h" 10 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
13 #include "net/dns/dns_query.h" 12 #include "net/dns/dns_query.h"
14 #include "net/dns/dns_response.h" 13 #include "net/dns/dns_response.h"
14 #include "net/dns/dns_session.h"
15 #include "net/socket/client_socket_factory.h" 15 #include "net/socket/client_socket_factory.h"
16 #include "net/udp/datagram_client_socket.h" 16 #include "net/udp/datagram_client_socket.h"
17 17
18 namespace net { 18 namespace net {
19 19
20 namespace { 20 namespace {
21 21
22 // Retry timeouts. 22 /*
23 const int kTimeoutsMs[] = {3000, 5000, 11000};
24 const int kMaxAttempts = arraysize(kTimeoutsMs);
25
26 // Returns the string representation of an IPAddressNumber. 23 // Returns the string representation of an IPAddressNumber.
27 std::string IPAddressToString(const IPAddressNumber& ip_address) { 24 std::string IPAddressToString(const IPAddressNumber& ip_address) {
28 IPEndPoint ip_endpoint(ip_address, 0); 25 IPEndPoint ip_endpoint(ip_address, 0);
29 struct sockaddr_storage addr; 26 struct sockaddr_storage addr;
30 size_t addr_len = sizeof(addr); 27 size_t addr_len = sizeof(addr);
31 struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr); 28 struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr);
32 if (!ip_endpoint.ToSockAddr(sockaddr, &addr_len)) 29 if (!ip_endpoint.ToSockAddr(sockaddr, &addr_len))
33 return ""; 30 return "";
34 return NetAddressToString(sockaddr, addr_len); 31 return NetAddressToString(sockaddr, addr_len);
35 } 32 }
36 33 */
37 }
38
39 DnsTransaction::Delegate::Delegate() {
40 }
41
42 DnsTransaction::Delegate::~Delegate() {
43 while (!registered_transactions_.empty()) {
44 DnsTransaction* transaction = *registered_transactions_.begin();
45 transaction->SetDelegate(NULL);
46 }
47 DCHECK(registered_transactions_.empty());
48 }
49
50 void DnsTransaction::Delegate::OnTransactionComplete(
51 int result,
52 const DnsTransaction* transaction,
53 const IPAddressList& ip_addresses) {
54 }
55
56 void DnsTransaction::Delegate::Attach(DnsTransaction* transaction) {
57 DCHECK(registered_transactions_.find(transaction) ==
58 registered_transactions_.end());
59 registered_transactions_.insert(transaction);
60 }
61
62 void DnsTransaction::Delegate::Detach(DnsTransaction* transaction) {
63 DCHECK(registered_transactions_.find(transaction) !=
64 registered_transactions_.end());
65 registered_transactions_.erase(transaction);
66 }
67
68 namespace {
69 34
70 class DnsTransactionStartParameters : public NetLog::EventParameters { 35 class DnsTransactionStartParameters : public NetLog::EventParameters {
71 public: 36 public:
72 DnsTransactionStartParameters(const IPEndPoint& dns_server, 37 DnsTransactionStartParameters(const IPEndPoint& dns_server,
73 const DnsTransaction::Key& key, 38 const base::StringPiece& qname,
39 uint16 qtype,
74 const NetLog::Source& source) 40 const NetLog::Source& source)
75 : dns_server_(dns_server), key_(key), source_(source) {} 41 : dns_server_(dns_server),
42 qname_(qname.data(), qname.length()),
43 qtype_(qtype),
44 source_(source) {}
76 45
77 virtual Value* ToValue() const { 46 virtual Value* ToValue() const {
78 std::string hostname;
79 DnsResponseBuffer(
80 reinterpret_cast<const uint8*>(key_.first.c_str()), key_.first.size()).
81 DNSName(&hostname);
82
83 DictionaryValue* dict = new DictionaryValue(); 47 DictionaryValue* dict = new DictionaryValue();
84 dict->SetString("dns_server", dns_server_.ToString()); 48 dict->SetString("dns_server", dns_server_.ToString());
85 dict->SetString("hostname", hostname); 49 dict->SetString("hostname", qname_);
86 dict->SetInteger("query_type", key_.second); 50 dict->SetInteger("query_type", qtype_);
87 if (source_.is_valid()) 51 if (source_.is_valid())
88 dict->Set("source_dependency", source_.ToValue()); 52 dict->Set("source_dependency", source_.ToValue());
89 return dict; 53 return dict;
90 } 54 }
91 55
92 private: 56 private:
93 const IPEndPoint dns_server_; 57 IPEndPoint dns_server_;
94 const DnsTransaction::Key key_; 58 std::string qname_;
59 uint16 qtype_;
95 const NetLog::Source source_; 60 const NetLog::Source source_;
96 }; 61 };
97 62
98 class DnsTransactionFinishParameters : public NetLog::EventParameters { 63 class DnsTransactionFinishParameters : public NetLog::EventParameters {
99 public: 64 public:
100 DnsTransactionFinishParameters(int net_error, 65 // TODO(szym): add rcode ?
101 const IPAddressList& ip_address_list) 66 DnsTransactionFinishParameters(int net_error, int answer_count)
102 : net_error_(net_error), ip_address_list_(ip_address_list) {} 67 : net_error_(net_error), answer_count_(answer_count) {}
103 68
104 virtual Value* ToValue() const { 69 virtual Value* ToValue() const {
105 ListValue* list = new ListValue();
106 for (IPAddressList::const_iterator it = ip_address_list_.begin();
107 it != ip_address_list_.end(); ++it)
108 list->Append(Value::CreateStringValue(IPAddressToString(*it)));
109
110 DictionaryValue* dict = new DictionaryValue(); 70 DictionaryValue* dict = new DictionaryValue();
111 if (net_error_) 71 if (net_error_)
112 dict->SetInteger("net_error", net_error_); 72 dict->SetInteger("net_error", net_error_);
113 dict->Set("address_list", list); 73 dict->SetInteger("answer_count", answer_count_);
114 return dict; 74 return dict;
115 } 75 }
116 76
117 private: 77 private:
118 const int net_error_; 78 const int net_error_;
119 const IPAddressList ip_address_list_; 79 const int answer_count_;
120 }; 80 };
121 81
122 class DnsTransactionRetryParameters : public NetLog::EventParameters { 82 class DnsTransactionRetryParameters : public NetLog::EventParameters {
123 public: 83 public:
124 DnsTransactionRetryParameters(int attempt_number, 84 DnsTransactionRetryParameters(int attempt_number,
125 const NetLog::Source& source) 85 const NetLog::Source& source)
126 : attempt_number_(attempt_number), source_(source) {} 86 : attempt_number_(attempt_number), source_(source) {}
127 87
128 virtual Value* ToValue() const { 88 virtual Value* ToValue() const {
129 DictionaryValue* dict = new DictionaryValue(); 89 DictionaryValue* dict = new DictionaryValue();
130 dict->SetInteger("attempt_number", attempt_number_); 90 dict->SetInteger("attempt_number", attempt_number_);
131 dict->Set("source_dependency", source_.ToValue()); 91 dict->Set("source_dependency", source_.ToValue());
132 return dict; 92 return dict;
133 } 93 }
134 94
135 private: 95 private:
136 const int attempt_number_; 96 const int attempt_number_;
137 const NetLog::Source source_; 97 const NetLog::Source source_;
138 }; 98 };
139 99
140 } // namespace 100 } // namespace
141 101
142 DnsTransaction::DnsTransaction(const IPEndPoint& dns_server, 102
143 const std::string& dns_name, 103 DnsTransaction::DnsTransaction(DnsSession* session,
144 uint16 query_type, 104 const base::StringPiece& qname,
145 const RandIntCallback& rand_int, 105 uint16 qtype,
146 ClientSocketFactory* socket_factory, 106 const ResultCallback& callback,
147 const BoundNetLog& source_net_log, 107 const BoundNetLog& source_net_log)
148 NetLog* net_log) 108 : session_(session),
149 : dns_server_(dns_server), 109 dns_server_(session->NextServer()),
150 key_(dns_name, query_type), 110 query_(new DnsQuery(session->NextId(), qname, qtype)),
151 delegate_(NULL), 111 callback_(callback),
152 query_(new DnsQuery(dns_name, query_type, rand_int)),
153 attempts_(0), 112 attempts_(0),
154 next_state_(STATE_NONE), 113 next_state_(STATE_NONE),
155 socket_factory_(socket_factory ? socket_factory :
156 ClientSocketFactory::GetDefaultFactory()),
157 ALLOW_THIS_IN_INITIALIZER_LIST( 114 ALLOW_THIS_IN_INITIALIZER_LIST(
158 io_callback_(this, &DnsTransaction::OnIOComplete)), 115 io_callback_(this, &DnsTransaction::OnIOComplete)),
159 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_DNS_TRANSACTION)) { 116 net_log_(BoundNetLog::Make(session->net_log(),
160 DCHECK(!rand_int.is_null()); 117 NetLog::SOURCE_DNS_TRANSACTION)) {
161 for (size_t i = 0; i < arraysize(kTimeoutsMs); ++i)
162 timeouts_ms_.push_back(base::TimeDelta::FromMilliseconds(kTimeoutsMs[i]));
163 net_log_.BeginEvent( 118 net_log_.BeginEvent(
164 NetLog::TYPE_DNS_TRANSACTION, 119 NetLog::TYPE_DNS_TRANSACTION,
165 make_scoped_refptr( 120 make_scoped_refptr(
166 new DnsTransactionStartParameters(dns_server_, key_, 121 new DnsTransactionStartParameters(dns_server_,
122 qname,
123 qtype,
167 source_net_log.source()))); 124 source_net_log.source())));
168 } 125 }
169 126
170 DnsTransaction::~DnsTransaction() { 127 DnsTransaction::~DnsTransaction() {}
171 SetDelegate(NULL);
172 }
173
174 void DnsTransaction::SetDelegate(Delegate* delegate) {
175 if (delegate == delegate_)
176 return;
177 if (delegate_)
178 delegate_->Detach(this);
179 delegate_ = delegate;
180 if (delegate_)
181 delegate_->Attach(this);
182 }
183 128
184 int DnsTransaction::Start() { 129 int DnsTransaction::Start() {
185 DCHECK_EQ(STATE_NONE, next_state_); 130 DCHECK_EQ(STATE_NONE, next_state_);
186 next_state_ = STATE_CONNECT; 131 next_state_ = STATE_CONNECT;
187 return DoLoop(OK); 132 return DoLoop(OK);
188 } 133 }
189 134
190 int DnsTransaction::DoLoop(int result) { 135 int DnsTransaction::DoLoop(int result) {
191 DCHECK_NE(STATE_NONE, next_state_); 136 DCHECK_NE(STATE_NONE, next_state_);
192 int rv = result; 137 int rv = result;
(...skipping 23 matching lines...) Expand all
216 NOTREACHED(); 161 NOTREACHED();
217 break; 162 break;
218 } 163 }
219 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 164 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
220 165
221 return rv; 166 return rv;
222 } 167 }
223 168
224 void DnsTransaction::DoCallback(int result) { 169 void DnsTransaction::DoCallback(int result) {
225 DCHECK_NE(result, ERR_IO_PENDING); 170 DCHECK_NE(result, ERR_IO_PENDING);
171 int answer_count = (result == OK) ? response()->answer_count() : 0;
226 net_log_.EndEvent( 172 net_log_.EndEvent(
227 NetLog::TYPE_DNS_TRANSACTION, 173 NetLog::TYPE_DNS_TRANSACTION,
228 make_scoped_refptr( 174 make_scoped_refptr(
229 new DnsTransactionFinishParameters(result, ip_addresses_))); 175 new DnsTransactionFinishParameters(result, answer_count)));
230 if (delegate_) 176 callback_.Run(this, result);
231 delegate_->OnTransactionComplete(result, this, ip_addresses_);
232 } 177 }
233 178
234 void DnsTransaction::OnIOComplete(int result) { 179 void DnsTransaction::OnIOComplete(int result) {
235 int rv = DoLoop(result); 180 int rv = DoLoop(result);
236 if (rv != ERR_IO_PENDING) 181 if (rv != ERR_IO_PENDING)
237 DoCallback(rv); 182 DoCallback(rv);
238 } 183 }
239 184
240 int DnsTransaction::DoConnect() { 185 int DnsTransaction::DoConnect() {
241 next_state_ = STATE_CONNECT_COMPLETE; 186 next_state_ = STATE_CONNECT_COMPLETE;
242 187
243 DCHECK_LT(attempts_, timeouts_ms_.size()); 188 StartTimer(session_->NextTimeout(attempts_));
244 StartTimer(timeouts_ms_[attempts_]); 189 ++attempts_;
245 attempts_++;
246 190
247 // TODO(agayev): keep all sockets around in case the server responds 191 // TODO(szym): keep all sockets around in case the server responds
248 // after its timeout; state machine will need to change to handle that. 192 // after its timeout; state machine will need to change to handle that.
249 socket_.reset(socket_factory_->CreateDatagramClientSocket( 193 // The current plan is to move socket management out to DnsSession.
194 // Hence also move retransmissions to DnsClient::Request.
195 socket_.reset(session_->socket_factory()->CreateDatagramClientSocket(
250 DatagramSocket::RANDOM_BIND, 196 DatagramSocket::RANDOM_BIND,
251 base::Bind(&base::RandInt), 197 base::Bind(&base::RandInt),
252 net_log_.net_log(), 198 net_log_.net_log(),
253 net_log_.source())); 199 net_log_.source()));
254 200
255 net_log_.AddEvent( 201 net_log_.AddEvent(
256 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED, 202 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED,
257 make_scoped_refptr( 203 make_scoped_refptr(
258 new DnsTransactionRetryParameters(attempts_, 204 new DnsTransactionRetryParameters(attempts_,
259 socket_->NetLog().source()))); 205 socket_->NetLog().source())));
(...skipping 22 matching lines...) Expand all
282 // Writing to UDP should not result in a partial datagram. 228 // Writing to UDP should not result in a partial datagram.
283 if (rv != query_->io_buffer()->size()) 229 if (rv != query_->io_buffer()->size())
284 return ERR_NAME_NOT_RESOLVED; 230 return ERR_NAME_NOT_RESOLVED;
285 231
286 next_state_ = STATE_READ_RESPONSE; 232 next_state_ = STATE_READ_RESPONSE;
287 return OK; 233 return OK;
288 } 234 }
289 235
290 int DnsTransaction::DoReadResponse() { 236 int DnsTransaction::DoReadResponse() {
291 next_state_ = STATE_READ_RESPONSE_COMPLETE; 237 next_state_ = STATE_READ_RESPONSE_COMPLETE;
292 response_.reset(new DnsResponse(query_.get())); 238 response_.reset(new DnsResponse());
293 return socket_->Read(response_->io_buffer(), 239 return socket_->Read(response_->io_buffer(),
294 response_->io_buffer()->size(), 240 response_->io_buffer()->size(),
295 &io_callback_); 241 &io_callback_);
296 } 242 }
297 243
298 int DnsTransaction::DoReadResponseComplete(int rv) { 244 int DnsTransaction::DoReadResponseComplete(int rv) {
299 DCHECK_NE(ERR_IO_PENDING, rv); 245 DCHECK_NE(ERR_IO_PENDING, rv);
300 RevokeTimer(); 246 RevokeTimer();
301 if (rv < 0) 247 if (rv < 0)
302 return rv; 248 return rv;
303 249
304 DCHECK(rv); 250 DCHECK(rv);
305 // TODO(agayev): when supporting EDNS0 we may need to do multiple reads 251 if (!response_->InitParse(rv, *query_))
306 // to read the whole response. 252 return ERR_DNS_MALFORMED_RESPONSE;
307 return response_->Parse(rv, &ip_addresses_); 253 // TODO(szym): define this flag value in dns_protocol
254 if (response_->flags1() & 2)
255 return ERR_DNS_SERVER_REQUIRES_TCP;
mmenke 2011/12/02 00:53:56 nit: Should use two space indent.
szym 2011/12/05 23:06:28 Done.
256 // TODO(szym): move this handling out of DnsTransaction?
257 if (response_->rcode() != dns_protocol::kRcodeNOERROR &&
258 response_->rcode() != dns_protocol::kRcodeNXDOMAIN)
mmenke 2011/12/02 00:53:56 nit: Use braces here.
szym 2011/12/05 23:06:28 Done.
259 return ERR_DNS_SERVER_FAILED;
260 // TODO(szym): add ERR_DNS_RR_NOT_FOUND?
261 if (response_->answer_count() == 0)
262 return ERR_NAME_NOT_RESOLVED;
263
264 return OK;
308 } 265 }
309 266
310 void DnsTransaction::StartTimer(base::TimeDelta delay) { 267 void DnsTransaction::StartTimer(base::TimeDelta delay) {
311 timer_.Start(FROM_HERE, delay, this, &DnsTransaction::OnTimeout); 268 timer_.Start(FROM_HERE, delay, this, &DnsTransaction::OnTimeout);
312 } 269 }
313 270
314 void DnsTransaction::RevokeTimer() { 271 void DnsTransaction::RevokeTimer() {
315 timer_.Stop(); 272 timer_.Stop();
316 } 273 }
317 274
318 void DnsTransaction::OnTimeout() { 275 void DnsTransaction::OnTimeout() {
319 DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE || 276 DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE ||
320 next_state_ == STATE_READ_RESPONSE_COMPLETE); 277 next_state_ == STATE_READ_RESPONSE_COMPLETE);
321 if (attempts_ == timeouts_ms_.size()) { 278 if (attempts_ == session_->config().attempts) {
322 DoCallback(ERR_DNS_TIMED_OUT); 279 DoCallback(ERR_DNS_TIMED_OUT);
323 return; 280 return;
324 } 281 }
325 next_state_ = STATE_CONNECT; 282 next_state_ = STATE_CONNECT;
326 query_.reset(query_->CloneWithNewId()); 283 query_.reset(query_->CloneWithNewId(session_->NextId()));
327 int rv = DoLoop(OK); 284 int rv = DoLoop(OK);
328 if (rv != ERR_IO_PENDING) 285 if (rv != ERR_IO_PENDING)
329 DoCallback(rv); 286 DoCallback(rv);
330 } 287 }
331 288
332 void DnsTransaction::set_timeouts_ms(
333 const std::vector<base::TimeDelta>& timeouts_ms) {
334 DCHECK_EQ(0u, attempts_);
335 timeouts_ms_ = timeouts_ms;
336 }
337
338 } // namespace net 289 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698