OLD | NEW |
---|---|
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 <deque> | |
6 #include <string> | |
7 #include <vector> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/memory/weak_ptr.h" | |
13 #include "base/message_loop.h" | |
14 #include "base/rand_util.h" | |
15 #include "base/stl_util.h" | |
16 #include "base/string_piece.h" | |
17 #include "base/threading/non_thread_safe.h" | |
18 #include "base/timer.h" | |
19 #include "net/base/completion_callback.h" | |
20 #include "net/base/dns_util.h" | |
21 #include "net/base/io_buffer.h" | |
22 #include "net/base/ip_endpoint.h" | |
23 #include "net/base/net_errors.h" | |
24 #include "net/base/net_log.h" | |
5 #include "net/dns/dns_client.h" | 25 #include "net/dns/dns_client.h" |
mmenke
2012/01/13 16:44:37
This should go first, above the other includes, pe
| |
6 | 26 #include "net/dns/dns_protocol.h" |
7 #include "base/bind.h" | 27 #include "net/dns/dns_query.h" |
8 #include "base/string_piece.h" | |
9 #include "net/base/net_errors.h" | |
10 #include "net/dns/dns_response.h" | 28 #include "net/dns/dns_response.h" |
11 #include "net/dns/dns_session.h" | 29 #include "net/dns/dns_session.h" |
12 #include "net/dns/dns_transaction.h" | |
13 #include "net/socket/client_socket_factory.h" | 30 #include "net/socket/client_socket_factory.h" |
31 #include "net/udp/datagram_client_socket.h" | |
14 | 32 |
15 namespace net { | 33 namespace net { |
16 | 34 |
17 DnsClient::Request::Request(const base::StringPiece& qname, | 35 namespace { |
18 uint16 qtype, | 36 |
19 const RequestCallback& callback) | 37 // Count labels in the fully-qualified name in DNS format. |
20 : qname_(qname.data(), qname.size()), | 38 int CountLabels(const std::string& name) { |
39 size_t count = 0; | |
40 for (size_t i = 0; i < name.size() && name[i]; i+= name[i] + 1) | |
cbentzel
2012/01/13 13:39:54
Nit: space between i and +=
| |
41 ++count; | |
42 return count; | |
43 } | |
44 | |
45 class StartParameters : public NetLog::EventParameters { | |
46 public: | |
47 StartParameters(const std::string& hostname, | |
48 uint16 qtype, | |
49 const NetLog::Source& source) | |
50 : hostname_(hostname), qtype_(qtype), source_(source) {} | |
51 | |
52 virtual Value* ToValue() const { | |
mmenke
2012/01/13 16:44:37
nit: OVERRIDE
| |
53 DictionaryValue* dict = new DictionaryValue(); | |
54 dict->SetString("hostname", hostname_); | |
55 dict->SetInteger("query_type", qtype_); | |
56 dict->Set("source_dependency", source_.ToValue()); | |
57 return dict; | |
58 } | |
59 | |
60 private: | |
61 std::string hostname_; | |
62 uint16 qtype_; | |
mmenke
2012/01/13 16:44:37
nit: Both of these can be const
| |
63 const NetLog::Source source_; | |
64 }; | |
65 | |
66 class ResponseParameters : public NetLog::EventParameters { | |
67 public: | |
68 ResponseParameters(int rcode, int answer_count, const NetLog::Source& source) | |
69 : rcode_(rcode), answer_count_(answer_count), source_(source) {} | |
70 | |
71 virtual Value* ToValue() const { | |
mmenke
2012/01/13 16:44:37
nit: OVERRIDE
| |
72 DictionaryValue* dict = new DictionaryValue(); | |
73 dict->SetInteger("rcode", rcode_); | |
74 dict->SetInteger("answer_count", answer_count_); | |
75 dict->Set("source_dependency", source_.ToValue()); | |
76 return dict; | |
77 } | |
78 | |
79 private: | |
80 int rcode_; | |
81 int answer_count_; | |
mmenke
2012/01/13 16:44:37
nit: Both of these can be const
| |
82 const NetLog::Source source_; | |
83 }; | |
84 | |
85 // ---------------------------------------------------------------------------- | |
86 | |
87 // A single asynchronous DNS exchange over UDP, which consists of sending out a | |
88 // DNS query, waiting for a response, and returning the response that it | |
89 // matches. Logging is done in the socket and in the outer DnsTransaction. | |
90 class DnsUDPAttempt { | |
91 public: | |
92 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, | |
93 const IPEndPoint& server, | |
94 scoped_ptr<DnsQuery> query, | |
95 const CompletionCallback& callback) | |
96 : next_state_(STATE_NONE), | |
97 socket_(socket.Pass()), | |
98 server_(server), | |
99 query_(query.Pass()), | |
100 callback_(callback) { | |
101 } | |
102 | |
103 // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously | |
104 // and calls |callback| upon completion. | |
105 int Start() { | |
106 DCHECK_EQ(STATE_NONE, next_state_); | |
107 next_state_ = STATE_CONNECT; | |
108 return DoLoop(OK); | |
109 } | |
110 | |
111 const DnsQuery* query() { | |
mmenke
2012/01/13 16:44:37
nit: const
| |
112 return query_.get(); | |
113 } | |
114 | |
115 const DatagramClientSocket* socket() const { | |
116 return socket_.get(); | |
117 } | |
118 | |
119 // Returns the response or NULL if has not received a matching response from | |
120 // the server. | |
121 const DnsResponse* response() const { | |
122 return (response_.get() != NULL && response_->Parser().IsValid()) ? | |
123 response_.get() : NULL; | |
124 } | |
125 | |
126 private: | |
127 enum State { | |
128 STATE_CONNECT, | |
129 STATE_SEND_QUERY, | |
130 STATE_SEND_QUERY_COMPLETE, | |
131 STATE_READ_RESPONSE, | |
132 STATE_READ_RESPONSE_COMPLETE, | |
133 STATE_NONE, | |
134 }; | |
135 | |
136 int DoLoop(int result) { | |
137 DCHECK_NE(STATE_NONE, next_state_); | |
138 int rv = result; | |
139 do { | |
140 State state = next_state_; | |
141 next_state_ = STATE_NONE; | |
142 switch (state) { | |
143 case STATE_CONNECT: | |
144 rv = DoConnect(); | |
145 break; | |
146 case STATE_SEND_QUERY: | |
147 rv = DoSendQuery(); | |
148 break; | |
149 case STATE_SEND_QUERY_COMPLETE: | |
150 rv = DoSendQueryComplete(rv); | |
151 break; | |
152 case STATE_READ_RESPONSE: | |
153 rv = DoReadResponse(); | |
154 break; | |
155 case STATE_READ_RESPONSE_COMPLETE: | |
156 rv = DoReadResponseComplete(rv); | |
157 break; | |
158 default: | |
159 NOTREACHED(); | |
160 break; | |
161 } | |
162 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
163 | |
164 return rv; | |
165 } | |
166 | |
167 int DoConnect() { | |
168 next_state_ = STATE_SEND_QUERY; | |
169 return socket_->Connect(server_); | |
170 } | |
171 | |
172 int DoSendQuery() { | |
173 next_state_ = STATE_SEND_QUERY_COMPLETE; | |
174 return socket_->Write(query_->io_buffer(), | |
175 query_->io_buffer()->size(), | |
176 base::Bind(&DnsUDPAttempt::OnIOComplete, | |
177 base::Unretained(this))); | |
178 } | |
179 | |
180 int DoSendQueryComplete(int rv) { | |
181 if (rv < 0) | |
182 return rv; | |
183 | |
184 // Writing to UDP should not result in a partial datagram. | |
185 if (rv != query_->io_buffer()->size()) | |
186 return ERR_MSG_TOO_BIG; | |
187 | |
188 next_state_ = STATE_READ_RESPONSE; | |
189 return OK; | |
190 } | |
191 | |
192 int DoReadResponse() { | |
193 next_state_ = STATE_READ_RESPONSE_COMPLETE; | |
194 response_.reset(new DnsResponse()); | |
195 return socket_->Read(response_->io_buffer(), | |
196 response_->io_buffer()->size(), | |
197 base::Bind(&DnsUDPAttempt::OnIOComplete, | |
198 base::Unretained(this))); | |
199 } | |
200 | |
201 int DoReadResponseComplete(int rv) { | |
202 DCHECK_NE(ERR_IO_PENDING, rv); | |
203 if (rv < 0) | |
204 return rv; | |
205 | |
206 DCHECK(rv); | |
207 if (!response_->InitParse(rv, *query_)) | |
208 return ERR_DNS_MALFORMED_RESPONSE; | |
209 if (response_->flags() & dns_protocol::kFlagTC) | |
210 return ERR_DNS_SERVER_REQUIRES_TCP; | |
211 if (response_->rcode() != dns_protocol::kRcodeNOERROR && | |
212 response_->rcode() != dns_protocol::kRcodeNXDOMAIN) { | |
213 return ERR_DNS_SERVER_FAILED; | |
214 } | |
215 if (response_->answer_count() == 0) | |
216 return ERR_NAME_NOT_RESOLVED; | |
217 | |
218 return OK; | |
219 } | |
220 | |
221 void OnIOComplete(int rv) { | |
222 rv = DoLoop(rv); | |
223 if (rv != ERR_IO_PENDING) | |
224 callback_.Run(rv); | |
225 } | |
226 | |
227 State next_state_; | |
228 | |
229 scoped_ptr<DatagramClientSocket> socket_; | |
230 IPEndPoint server_; | |
231 scoped_ptr<DnsQuery> query_; | |
232 | |
233 scoped_ptr<DnsResponse> response_; | |
234 | |
235 CompletionCallback callback_; | |
mmenke
2012/01/13 16:44:37
nit: DISALLOW_COPY_AND_ASSIGN
| |
236 }; | |
237 | |
238 // ---------------------------------------------------------------------------- | |
239 | |
240 // Implements DnsTransaction. Configuration is supplied by DnsSession. | |
241 // The suffix list is built according to the DnsConfig from the session. | |
242 // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout. | |
243 // The first server to attempt on each query is given by | |
244 // DnsSession::NextFirstServerIndex, and the order is round-robin afterwards. | |
245 // Each server is attempted DnsConfig::attempts times. | |
246 class DnsTransactionImpl : public DnsTransaction, | |
247 public base::NonThreadSafe, | |
248 public base::SupportsWeakPtr<DnsTransactionImpl> { | |
249 public: | |
250 DnsTransactionImpl(DnsSession* session, | |
251 const std::string& hostname, | |
252 uint16 qtype, | |
253 const DnsClient::CallbackType& callback, | |
254 const BoundNetLog& source_net_log) | |
255 : session_(session), | |
256 hostname_(hostname), | |
21 qtype_(qtype), | 257 qtype_(qtype), |
22 callback_(callback) { | 258 callback_(callback), |
23 } | 259 net_log_(BoundNetLog::Make(session->net_log(), |
24 | 260 NetLog::SOURCE_DNS_TRANSACTION)), |
25 DnsClient::Request::~Request() {} | 261 successful_attempt_(NULL) { |
cbentzel
2012/01/13 13:39:54
first_server_index_ should be initialized - yeah,
| |
26 | 262 DCHECK(session_); |
27 // Implementation of DnsClient that uses DnsTransaction to serve requests. | 263 DCHECK(!hostname_.empty()); |
264 DCHECK(!callback_.is_null()); | |
265 | |
cbentzel
2012/01/13 13:39:54
Should this check if qtype is one of the known typ
| |
266 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, make_scoped_refptr( | |
267 new StartParameters(hostname_, qtype_, source_net_log.source()))); | |
268 | |
269 int rv = PrepareSearch(); | |
cbentzel
2012/01/13 13:39:54
Not really sure if I like having all this in the c
szym
2012/01/13 15:43:40
Do you mean move PrepareSearch to Start? I'd rathe
cbentzel
2012/01/13 18:12:59
I did mean do it in DnsClient::CreateTransaction,
| |
270 if (rv == OK) | |
271 rv = StartQuery(); | |
272 if (rv != ERR_IO_PENDING) { | |
273 DCHECK_NE(OK, rv); | |
274 DCHECK_NE(ERR_NAME_NOT_RESOLVED, rv); | |
275 // Unexpected synchronous completion. Use WeakPtr in case the user | |
276 // destroys the transaction before the task is executed. | |
277 MessageLoop::current()->PostTask( | |
278 FROM_HERE, | |
279 base::Bind(&DnsTransactionImpl::DoCallback, AsWeakPtr(), rv)); | |
280 } | |
281 } | |
282 | |
283 virtual ~DnsTransactionImpl() { | |
284 STLDeleteElements(&attempts_); | |
285 if (!callback_.is_null()) { | |
286 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
287 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, | |
288 ERR_ABORTED); | |
289 } | |
290 } | |
291 | |
292 virtual const std::string& GetHostname() const OVERRIDE { | |
293 DCHECK(CalledOnValidThread()); | |
294 return hostname_; | |
295 } | |
296 | |
297 virtual uint16 GetType() const OVERRIDE { | |
298 DCHECK(CalledOnValidThread()); | |
299 return qtype_; | |
300 } | |
301 | |
302 private: | |
303 // Prepares |qnames_| according to the DnsConfig. | |
304 int PrepareSearch() { | |
305 const DnsConfig& config = session_->config(); | |
306 | |
307 std::string hostname; | |
cbentzel
2012/01/13 13:39:54
It would be nice to use a better variable name tha
szym
2012/01/13 15:43:40
I could use dotted_hostname for the other case.
| |
308 if (!DNSDomainFromDot(hostname_, &hostname)) | |
309 return ERR_INVALID_ARGUMENT; | |
310 | |
311 if (hostname_[hostname_.size() - 1] == '.') { | |
312 // It's a fully-qualified name, no suffix search. | |
313 qnames_.push_back(hostname); | |
314 return OK; | |
315 } | |
316 | |
317 // Set true when |hostname| is put on the list. | |
318 bool had_hostname = false; | |
319 | |
320 int ndots = CountLabels(hostname) - 1; | |
321 if (ndots >= config.ndots) { | |
322 qnames_.push_back(hostname); | |
323 had_hostname = true; | |
324 } | |
325 | |
326 std::string qname; | |
327 for (size_t i = 0; i < config.search.size(); ++i) { | |
328 // Ignore invalid (too long) combinations. | |
329 if (!DNSDomainFromDot(hostname_ + "." + config.search[i], &qname)) | |
330 continue; | |
331 if (qname.size() == hostname.size()) { | |
cbentzel
2012/01/13 13:39:54
Interesting - is an empty suffix allowed? Or is th
szym
2012/01/13 15:43:40
DNSDomainFromDot always appends the root domain at
| |
332 if (had_hostname) | |
cbentzel
2012/01/13 13:39:54
Do you want to make this more generic in the loop
szym
2012/01/13 15:43:40
I think it'd make sense to do this filtering at th
| |
333 continue; | |
334 had_hostname = true; | |
335 } | |
336 qnames_.push_back(qname); | |
337 } | |
338 | |
339 if (!had_hostname) | |
340 qnames_.push_back(hostname); | |
341 | |
342 return OK; | |
343 } | |
344 | |
345 void DoCallback(int rv) { | |
346 if (callback_.is_null()) | |
347 return; | |
348 DCHECK_NE(ERR_IO_PENDING, rv); | |
349 DCHECK(rv != OK || successful_attempt_ != NULL); | |
350 | |
351 DnsClient::CallbackType callback = callback_; | |
352 callback_.Reset(); | |
353 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, rv); | |
354 callback.Run(this, | |
355 rv, | |
356 successful_attempt_ ? successful_attempt_->response() : NULL); | |
357 } | |
358 | |
359 // Makes another attempt at the current name, |qnames_.front()|, using the | |
360 // next nameserver. | |
361 int MakeAttempt() { | |
362 int attempt_number = attempts_.size(); | |
363 | |
364 scoped_ptr<DatagramClientSocket> socket( | |
365 session_->socket_factory()->CreateDatagramClientSocket( | |
366 DatagramSocket::RANDOM_BIND, | |
367 base::Bind(&base::RandInt), | |
368 net_log_.net_log(), | |
369 net_log_.source())); | |
370 | |
371 uint16 id = session_->NextQueryId(); | |
372 scoped_ptr<DnsQuery> query; | |
373 if (attempts_.empty()) { | |
374 query.reset(new DnsQuery(id, qnames_.front(), qtype_)); | |
375 } else { | |
376 query.reset(attempts_[0]->query()->CloneWithNewId(id)); | |
cbentzel
2012/01/13 13:39:54
Note to self: See if this any easier.
| |
377 } | |
378 | |
379 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, make_scoped_refptr( | |
380 new NetLogSourceParameter("socket", socket->NetLog().source()))); | |
mmenke
2012/01/13 16:44:37
Think it would be a little clearer if you also log
szym
2012/01/13 17:17:42
The reason why I don't include attempt_number is b
mmenke
2012/01/13 17:22:58
I was just thinking that it would be clearer for t
| |
381 | |
382 const DnsConfig& config = session_->config(); | |
383 | |
384 int server_index = first_server_index_ + | |
cbentzel
2012/01/13 13:39:54
You should check for 0 length config.nameservers,
szym
2012/01/13 15:43:40
If |config.nameservers| is empty, the config is in
cbentzel
2012/01/13 18:12:59
What if the config changed while the DnsTransactio
szym
2012/01/13 20:06:17
DnsConfig is const in DnsSession, so DnsTransactio
| |
385 (attempt_number % config.nameservers.size()); | |
386 | |
387 DnsUDPAttempt* attempt = new DnsUDPAttempt( | |
388 socket.Pass(), | |
389 config.nameservers[server_index], | |
390 query.Pass(), | |
391 base::Bind(&DnsTransactionImpl::OnAttemptComplete, | |
392 base::Unretained(this), | |
393 attempt_number)); | |
394 | |
395 base::TimeDelta timeout = session_->NextTimeout(attempt_number); | |
396 timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); | |
397 attempts_.push_back(attempt); | |
398 return attempt->Start(); | |
399 } | |
400 | |
401 // Begins query for the current name. Makes the first attempt. | |
402 int StartQuery() { | |
403 std::string dotted_qname = DNSDomainToString(qnames_.front()); | |
404 net_log_.BeginEvent( | |
405 NetLog::TYPE_DNS_TRANSACTION_QUERY, | |
mmenke
2012/01/13 17:16:24
Where do you log the corresponding end event?
| |
406 make_scoped_refptr(new NetLogStringParameter("qname", dotted_qname))); | |
407 | |
408 first_server_index_ = session_->NextFirstServerIndex(); | |
409 | |
410 STLDeleteElements(&attempts_); | |
411 return MakeAttempt(); | |
412 } | |
413 | |
414 void OnAttemptComplete(int attempt_number, int rv) { | |
415 timer_.Stop(); | |
416 | |
417 const DnsUDPAttempt* attempt = attempts_[attempt_number]; | |
418 | |
419 net_log_.AddEvent( | |
420 NetLog::TYPE_DNS_TRANSACTION_RESPONSE, | |
421 make_scoped_refptr( | |
422 new NetLogSourceParameter("socket", | |
423 attempt->socket()->NetLog().source()))); | |
424 | |
425 switch (rv) { | |
426 case ERR_NAME_NOT_RESOLVED: | |
427 // Try next suffix. | |
428 qnames_.pop_front(); | |
429 if (qnames_.empty()) | |
430 rv = ERR_NAME_NOT_RESOLVED; | |
431 else | |
432 rv = StartQuery(); | |
433 break; | |
434 case OK: | |
435 successful_attempt_ = attempt; | |
436 break; | |
437 default: | |
438 // TODO(szym): Some nameservers could fail and we should just ignore | |
439 // them. | |
440 break; | |
441 } | |
442 if (rv != ERR_IO_PENDING) | |
443 DoCallback(rv); | |
444 } | |
445 | |
446 void OnTimeout() { | |
447 const DnsConfig& config = session_->config(); | |
448 if (attempts_.size() == config.attempts * config.nameservers.size()) { | |
449 DoCallback(ERR_DNS_TIMED_OUT); | |
450 return; | |
451 } | |
452 int rv = MakeAttempt(); | |
453 if (rv != ERR_IO_PENDING) | |
454 DoCallback(rv); | |
455 } | |
456 | |
457 scoped_refptr<DnsSession> session_; | |
458 std::string hostname_; | |
459 uint16 qtype_; | |
460 // Set to NULL once the transaction completes. | |
cbentzel
2012/01/13 13:39:54
Nit: perhaps null instead of NULL - NULL implies p
| |
461 DnsClient::CallbackType callback_; | |
462 | |
463 BoundNetLog net_log_; | |
464 | |
465 // Search list of fully-qualified DNS names to query next (in DNS format). | |
466 std::deque<std::string> qnames_; | |
cbentzel
2012/01/13 13:39:54
deque not really needed here, since just doing pus
szym
2012/01/13 15:43:40
Need qnames_.pop_front().
| |
467 | |
468 // List of attempts for the current name. | |
469 std::vector<DnsUDPAttempt*> attempts_; | |
470 // The one of the |attempts_| that succeeded first. | |
mmenke
2012/01/13 16:44:37
Nit: This is the member of |attempts_| that succe
| |
471 const DnsUDPAttempt* successful_attempt_; | |
472 | |
473 // Index of the first server to try on each search query. | |
474 int first_server_index_; | |
475 | |
476 base::OneShotTimer<DnsTransactionImpl> timer_; | |
477 | |
478 DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl); | |
479 }; | |
480 | |
481 // ---------------------------------------------------------------------------- | |
482 | |
483 // Implementation of DnsClient that returns instances of DnsTransactionImpl. | |
28 class DnsClientImpl : public DnsClient { | 484 class DnsClientImpl : public DnsClient { |
mmenke
2012/01/13 16:44:37
Is there a compelling reason to keep DnsClient and
szym
2012/01/13 17:17:42
The reason I'd keep them separate is so that we ca
mmenke
2012/01/13 17:22:58
Ah, right. Sounds good to me.
| |
29 public: | 485 public: |
30 class RequestImpl : public Request { | |
31 public: | |
32 RequestImpl(const base::StringPiece& qname, | |
33 uint16 qtype, | |
34 const RequestCallback& callback, | |
35 DnsSession* session, | |
36 const BoundNetLog& net_log) | |
37 : Request(qname, qtype, callback), | |
38 session_(session), | |
39 net_log_(net_log) { | |
40 } | |
41 | |
42 virtual int Start() OVERRIDE { | |
43 transaction_.reset(new DnsTransaction( | |
44 session_, | |
45 qname(), | |
46 qtype(), | |
47 base::Bind(&RequestImpl::OnComplete, base::Unretained(this)), | |
48 net_log_)); | |
49 return transaction_->Start(); | |
50 } | |
51 | |
52 void OnComplete(DnsTransaction* transaction, int rv) { | |
53 DCHECK_EQ(transaction_.get(), transaction); | |
54 // TODO(szym): | |
55 // - handle retransmissions here instead of DnsTransaction | |
56 // - handle rcode and flags here instead of DnsTransaction | |
57 // - update RTT in DnsSession | |
58 // - perform suffix search | |
59 // - handle DNS over TCP | |
60 DoCallback(rv, (rv == OK) ? transaction->response() : NULL); | |
61 } | |
62 | |
63 private: | |
64 scoped_refptr<DnsSession> session_; | |
65 BoundNetLog net_log_; | |
66 scoped_ptr<DnsTransaction> transaction_; | |
67 }; | |
68 | |
69 explicit DnsClientImpl(DnsSession* session) { | 486 explicit DnsClientImpl(DnsSession* session) { |
70 session_ = session; | 487 session_ = session; |
71 } | 488 } |
72 | 489 |
73 virtual Request* CreateRequest( | 490 virtual scoped_ptr<DnsTransaction> CreateTransaction( |
74 const base::StringPiece& qname, | 491 const std::string& hostname, |
75 uint16 qtype, | 492 uint16 qtype, |
76 const RequestCallback& callback, | 493 const CallbackType& callback, |
77 const BoundNetLog& source_net_log) OVERRIDE { | 494 const BoundNetLog& source_net_log) OVERRIDE { |
78 return new RequestImpl(qname, qtype, callback, session_, source_net_log); | 495 return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(session_, |
496 hostname, | |
497 qtype, | |
498 callback, | |
499 source_net_log)); | |
79 } | 500 } |
80 | 501 |
81 private: | 502 private: |
82 scoped_refptr<DnsSession> session_; | 503 scoped_refptr<DnsSession> session_; |
83 }; | 504 }; |
84 | 505 |
506 } // namespace | |
507 | |
85 // static | 508 // static |
86 DnsClient* DnsClient::CreateClient(DnsSession* session) { | 509 scoped_ptr<DnsClient> DnsClient::CreateClient(DnsSession* session) { |
87 return new DnsClientImpl(session); | 510 return scoped_ptr<DnsClient>(new DnsClientImpl(session)); |
88 } | 511 } |
89 | 512 |
90 } // namespace net | 513 } // namespace net |
91 | 514 |
OLD | NEW |