Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/mdns_client_impl.h" | 5 #include "net/dns/mdns_client_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <queue> | 8 #include <queue> |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
| 11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/time/clock.h" | |
| 12 #include "base/time/default_clock.h" | 14 #include "base/time/default_clock.h" |
| 13 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "base/timer/timer.h" | |
| 14 #include "net/base/dns_util.h" | 17 #include "net/base/dns_util.h" |
| 15 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 16 #include "net/base/net_log.h" | 19 #include "net/base/net_log.h" |
| 17 #include "net/base/rand_callback.h" | 20 #include "net/base/rand_callback.h" |
| 18 #include "net/dns/dns_protocol.h" | 21 #include "net/dns/dns_protocol.h" |
| 19 #include "net/dns/record_rdata.h" | 22 #include "net/dns/record_rdata.h" |
| 20 #include "net/udp/datagram_socket.h" | 23 #include "net/udp/datagram_socket.h" |
| 21 | 24 |
| 22 // TODO(gene): Remove this temporary method of disabling NSEC support once it | 25 // TODO(gene): Remove this temporary method of disabling NSEC support once it |
| 23 // becomes clear whether this feature should be | 26 // becomes clear whether this feature should be |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 | 191 |
| 189 void MDnsConnection::OnDatagramReceived( | 192 void MDnsConnection::OnDatagramReceived( |
| 190 DnsResponse* response, | 193 DnsResponse* response, |
| 191 const IPEndPoint& recv_addr, | 194 const IPEndPoint& recv_addr, |
| 192 int bytes_read) { | 195 int bytes_read) { |
| 193 // TODO(noamsml): More sophisticated error handling. | 196 // TODO(noamsml): More sophisticated error handling. |
| 194 DCHECK_GT(bytes_read, 0); | 197 DCHECK_GT(bytes_read, 0); |
| 195 delegate_->HandlePacket(response, bytes_read); | 198 delegate_->HandlePacket(response, bytes_read); |
| 196 } | 199 } |
| 197 | 200 |
| 198 MDnsClientImpl::Core::Core() : connection_(new MDnsConnection(this)) { | 201 MDnsClientImpl::Core::Core() |
| 202 : clock_(new base::DefaultClock), | |
| 203 cleanup_timer_(new base::Timer(false, false)), | |
| 204 connection_(new MDnsConnection(this)) { | |
| 199 } | 205 } |
| 200 | 206 |
| 201 MDnsClientImpl::Core::~Core() { | 207 MDnsClientImpl::Core::~Core() { |
| 202 STLDeleteValues(&listeners_); | 208 STLDeleteValues(&listeners_); |
| 203 } | 209 } |
| 204 | 210 |
| 205 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { | 211 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { |
| 206 return connection_->Init(socket_factory); | 212 return connection_->Init(socket_factory); |
| 207 } | 213 } |
| 208 | 214 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 234 // TODO(noamsml): duplicate query suppression. | 240 // TODO(noamsml): duplicate query suppression. |
| 235 if (!(response->flags() & dns_protocol::kFlagResponse)) | 241 if (!(response->flags() & dns_protocol::kFlagResponse)) |
| 236 return; // Message is a query. ignore it. | 242 return; // Message is a query. ignore it. |
| 237 | 243 |
| 238 DnsRecordParser parser = response->Parser(); | 244 DnsRecordParser parser = response->Parser(); |
| 239 unsigned answer_count = response->answer_count() + | 245 unsigned answer_count = response->answer_count() + |
| 240 response->additional_answer_count(); | 246 response->additional_answer_count(); |
| 241 | 247 |
| 242 for (unsigned i = 0; i < answer_count; i++) { | 248 for (unsigned i = 0; i < answer_count; i++) { |
| 243 offset = parser.GetOffset(); | 249 offset = parser.GetOffset(); |
| 244 scoped_ptr<const RecordParsed> record = RecordParsed::CreateFrom( | 250 scoped_ptr<const RecordParsed> record = |
| 245 &parser, base::Time::Now()); | 251 RecordParsed::CreateFrom(&parser, clock_->Now()); |
| 246 | 252 |
| 247 if (!record) { | 253 if (!record) { |
| 248 DVLOG(1) << "Could not understand an mDNS record."; | 254 DVLOG(1) << "Could not understand an mDNS record."; |
| 249 | 255 |
| 250 if (offset == parser.GetOffset()) { | 256 if (offset == parser.GetOffset()) { |
| 251 DVLOG(1) << "Abandoned parsing the rest of the packet."; | 257 DVLOG(1) << "Abandoned parsing the rest of the packet."; |
| 252 return; // The parser did not advance, abort reading the packet. | 258 return; // The parser did not advance, abort reading the packet. |
| 253 } else { | 259 } else { |
| 254 continue; // We may be able to extract other records from the packet. | 260 continue; // We may be able to extract other records from the packet. |
| 255 } | 261 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 } | 294 } |
| 289 | 295 |
| 290 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { | 296 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { |
| 291 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type()); | 297 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type()); |
| 292 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>(); | 298 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>(); |
| 293 DCHECK(rdata); | 299 DCHECK(rdata); |
| 294 | 300 |
| 295 // Remove all cached records matching the nonexistent RR types. | 301 // Remove all cached records matching the nonexistent RR types. |
| 296 std::vector<const RecordParsed*> records_to_remove; | 302 std::vector<const RecordParsed*> records_to_remove; |
| 297 | 303 |
| 298 cache_.FindDnsRecords(0, record->name(), &records_to_remove, | 304 cache_.FindDnsRecords(0, record->name(), &records_to_remove, clock_->Now()); |
| 299 base::Time::Now()); | |
| 300 | 305 |
| 301 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); | 306 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); |
| 302 i != records_to_remove.end(); i++) { | 307 i != records_to_remove.end(); i++) { |
| 303 if ((*i)->type() == dns_protocol::kTypeNSEC) | 308 if ((*i)->type() == dns_protocol::kTypeNSEC) |
| 304 continue; | 309 continue; |
| 305 if (!rdata->GetBit((*i)->type())) { | 310 if (!rdata->GetBit((*i)->type())) { |
| 306 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i)); | 311 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i)); |
| 307 DCHECK(record_removed); | 312 DCHECK(record_removed); |
| 308 OnRecordRemoved(record_removed.get()); | 313 OnRecordRemoved(record_removed.get()); |
| 309 } | 314 } |
| 310 } | 315 } |
| 311 | 316 |
| 312 // Alert all listeners waiting for the nonexistent RR types. | 317 // Alert all listeners waiting for the nonexistent RR types. |
| 313 ListenerMap::iterator i = | 318 ListenerMap::iterator i = |
| 314 listeners_.upper_bound(ListenerKey(record->name(), 0)); | 319 listeners_.upper_bound(ListenerKey(record->name(), 0)); |
| 315 for (; i != listeners_.end() && i->first.first == record->name(); i++) { | 320 for (; i != listeners_.end() && i->first.first == record->name(); i++) { |
| 316 if (!rdata->GetBit(i->first.second)) { | 321 if (!rdata->GetBit(i->first.second)) { |
| 317 FOR_EACH_OBSERVER(MDnsListenerImpl, *i->second, AlertNsecRecord()); | 322 FOR_EACH_OBSERVER(MDnsListenerImpl, *i->second, AlertNsecRecord()); |
| 318 } | 323 } |
| 319 } | 324 } |
| 320 } | 325 } |
| 321 | 326 |
| 322 void MDnsClientImpl::Core::OnConnectionError(int error) { | 327 void MDnsClientImpl::Core::OnConnectionError(int error) { |
| 323 // TODO(noamsml): On connection error, recreate connection and flush cache. | 328 // TODO(noamsml): On connection error, recreate connection and flush cache. |
| 324 } | 329 } |
| 325 | 330 |
| 331 void MDnsClientImpl::Core::set_cleanup_timer_for_test( | |
| 332 scoped_ptr<base::Timer> timer) { | |
| 333 cleanup_timer_ = timer.Pass(); | |
| 334 } | |
| 335 | |
| 336 void MDnsClientImpl::Core::set_clock_for_test(scoped_ptr<base::Clock> clock) { | |
| 337 clock_ = clock.Pass(); | |
| 338 } | |
| 339 | |
| 326 void MDnsClientImpl::Core::AlertListeners( | 340 void MDnsClientImpl::Core::AlertListeners( |
| 327 MDnsCache::UpdateType update_type, | 341 MDnsCache::UpdateType update_type, |
| 328 const ListenerKey& key, | 342 const ListenerKey& key, |
| 329 const RecordParsed* record) { | 343 const RecordParsed* record) { |
| 330 ListenerMap::iterator listener_map_iterator = listeners_.find(key); | 344 ListenerMap::iterator listener_map_iterator = listeners_.find(key); |
| 331 if (listener_map_iterator == listeners_.end()) return; | 345 if (listener_map_iterator == listeners_.end()) return; |
| 332 | 346 |
| 333 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, | 347 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, |
| 334 HandleRecordUpdate(update_type, record)); | 348 HandleRecordUpdate(update_type, record)); |
| 335 } | 349 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { | 387 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { |
| 374 ListenerMap::iterator found = listeners_.find(key); | 388 ListenerMap::iterator found = listeners_.find(key); |
| 375 if (found != listeners_.end() && !found->second->might_have_observers()) { | 389 if (found != listeners_.end() && !found->second->might_have_observers()) { |
| 376 delete found->second; | 390 delete found->second; |
| 377 listeners_.erase(found); | 391 listeners_.erase(found); |
| 378 } | 392 } |
| 379 } | 393 } |
| 380 | 394 |
| 381 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { | 395 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { |
| 382 // Cleanup is already scheduled, no need to do anything. | 396 // Cleanup is already scheduled, no need to do anything. |
| 383 if (cleanup == scheduled_cleanup_) return; | 397 if (cleanup == scheduled_cleanup_) { |
| 398 return; | |
| 399 } | |
| 384 scheduled_cleanup_ = cleanup; | 400 scheduled_cleanup_ = cleanup; |
| 385 | 401 |
| 386 // This cancels the previously scheduled cleanup. | 402 // This cancels the previously scheduled cleanup. |
| 387 cleanup_callback_.Reset(base::Bind( | 403 cleanup_timer_->Stop(); |
| 388 &MDnsClientImpl::Core::DoCleanup, base::Unretained(this))); | |
| 389 | 404 |
| 390 // If |cleanup| is empty, then no cleanup necessary. | 405 // If |cleanup| is empty, then no cleanup necessary. |
| 391 if (cleanup != base::Time()) { | 406 if (cleanup != base::Time()) { |
| 392 base::MessageLoop::current()->PostDelayedTask( | 407 cleanup_timer_->Start( |
| 393 FROM_HERE, | 408 FROM_HERE, std::max(base::TimeDelta(), cleanup - clock_->Now()), |
| 394 cleanup_callback_.callback(), | 409 base::Bind(&MDnsClientImpl::Core::DoCleanup, base::Unretained(this))); |
| 395 cleanup - base::Time::Now()); | |
| 396 } | 410 } |
| 397 } | 411 } |
| 398 | 412 |
| 399 void MDnsClientImpl::Core::DoCleanup() { | 413 void MDnsClientImpl::Core::DoCleanup() { |
| 400 cache_.CleanupRecords(base::Time::Now(), base::Bind( | 414 cache_.CleanupRecords(clock_->Now(), |
| 401 &MDnsClientImpl::Core::OnRecordRemoved, base::Unretained(this))); | 415 base::Bind(&MDnsClientImpl::Core::OnRecordRemoved, |
|
mark a. foltz
2015/02/25 21:44:07
What cancels this callback when MDnsClientImpl is
Kevin M
2015/02/26 01:04:40
DoCleanup() can't be called if the MdnsClientImpl
mark a. foltz
2015/02/26 01:18:03
Acknowledged.
| |
| 416 base::Unretained(this))); | |
| 402 | 417 |
| 403 ScheduleCleanup(cache_.next_expiration()); | 418 ScheduleCleanup(cache_.next_expiration()); |
| 404 } | 419 } |
| 405 | 420 |
| 406 void MDnsClientImpl::Core::OnRecordRemoved( | 421 void MDnsClientImpl::Core::OnRecordRemoved( |
| 407 const RecordParsed* record) { | 422 const RecordParsed* record) { |
| 408 AlertListeners(MDnsCache::RecordRemoved, | 423 AlertListeners(MDnsCache::RecordRemoved, |
| 409 ListenerKey(record->name(), record->type()), record); | 424 ListenerKey(record->name(), record->type()), record); |
| 410 } | 425 } |
| 411 | 426 |
| 412 void MDnsClientImpl::Core::QueryCache( | 427 void MDnsClientImpl::Core::QueryCache( |
| 413 uint16 rrtype, const std::string& name, | 428 uint16 rrtype, const std::string& name, |
| 414 std::vector<const RecordParsed*>* records) const { | 429 std::vector<const RecordParsed*>* records) const { |
| 415 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); | 430 cache_.FindDnsRecords(rrtype, name, records, clock_->Now()); |
| 416 } | 431 } |
| 417 | 432 |
| 418 MDnsClientImpl::MDnsClientImpl() { | 433 MDnsClientImpl::MDnsClientImpl() { |
| 419 } | 434 } |
| 420 | 435 |
| 421 MDnsClientImpl::~MDnsClientImpl() { | 436 MDnsClientImpl::~MDnsClientImpl() { |
| 422 } | 437 } |
| 423 | 438 |
| 424 bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) { | 439 bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) { |
| 425 DCHECK(!core_.get()); | 440 DCHECK(!core_.get()); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 static_cast<int>(base::Time::kMillisecondsPerSecond * | 581 static_cast<int>(base::Time::kMillisecondsPerSecond * |
| 567 kListenerRefreshRatio1 * ttl_)); | 582 kListenerRefreshRatio1 * ttl_)); |
| 568 | 583 |
| 569 base::Time next_refresh2 = last_update_ + base::TimeDelta::FromMilliseconds( | 584 base::Time next_refresh2 = last_update_ + base::TimeDelta::FromMilliseconds( |
| 570 static_cast<int>(base::Time::kMillisecondsPerSecond * | 585 static_cast<int>(base::Time::kMillisecondsPerSecond * |
| 571 kListenerRefreshRatio2 * ttl_)); | 586 kListenerRefreshRatio2 * ttl_)); |
| 572 | 587 |
| 573 base::MessageLoop::current()->PostDelayedTask( | 588 base::MessageLoop::current()->PostDelayedTask( |
| 574 FROM_HERE, | 589 FROM_HERE, |
| 575 next_refresh_.callback(), | 590 next_refresh_.callback(), |
| 576 next_refresh1 - base::Time::Now()); | 591 next_refresh1 - base::Time::Now()); |
|
mark a. foltz
2015/02/25 21:44:06
If we are converting this class to use base::Clock
Kevin M
2015/02/26 01:04:40
This required a bit of plumbing to route the Clock
| |
| 577 | 592 |
| 578 base::MessageLoop::current()->PostDelayedTask( | 593 base::MessageLoop::current()->PostDelayedTask( |
| 579 FROM_HERE, | 594 FROM_HERE, |
| 580 next_refresh_.callback(), | 595 next_refresh_.callback(), |
| 581 next_refresh2 - base::Time::Now()); | 596 next_refresh2 - base::Time::Now()); |
|
mark a. foltz
2015/02/25 21:44:07
Ditto.
Kevin M
2015/02/26 01:04:40
Done.
| |
| 582 } | 597 } |
| 583 | 598 |
| 584 void MDnsListenerImpl::DoRefresh() { | 599 void MDnsListenerImpl::DoRefresh() { |
| 585 client_->core()->SendQuery(rrtype_, name_); | 600 client_->core()->SendQuery(rrtype_, name_); |
| 586 } | 601 } |
| 587 | 602 |
| 588 MDnsTransactionImpl::MDnsTransactionImpl( | 603 MDnsTransactionImpl::MDnsTransactionImpl( |
| 589 uint16 rrtype, | 604 uint16 rrtype, |
| 590 const std::string& name, | 605 const std::string& name, |
| 591 int flags, | 606 int flags, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 | 741 |
| 727 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 742 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
| 728 TriggerCallback(RESULT_NSEC, NULL); | 743 TriggerCallback(RESULT_NSEC, NULL); |
| 729 } | 744 } |
| 730 | 745 |
| 731 void MDnsTransactionImpl::OnCachePurged() { | 746 void MDnsTransactionImpl::OnCachePurged() { |
| 732 // TODO(noamsml): Cache purge situations not yet implemented | 747 // TODO(noamsml): Cache purge situations not yet implemented |
| 733 } | 748 } |
| 734 | 749 |
| 735 } // namespace net | 750 } // namespace net |
| OLD | NEW |