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

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

Issue 937743003: Fix MDnsClient's cache entry cleanup logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use base::Clock throughout MDnsClientImpl Created 5 years, 9 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 unified diff | Download patch
OLDNEW
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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 multicast_addr_ = GetMDnsIPEndPoint(end_point.GetFamily()); 76 multicast_addr_ = GetMDnsIPEndPoint(end_point.GetFamily());
74 return DoLoop(0); 77 return DoLoop(0);
75 } 78 }
76 79
77 int MDnsConnection::SocketHandler::DoLoop(int rv) { 80 int MDnsConnection::SocketHandler::DoLoop(int rv) {
78 do { 81 do {
79 if (rv > 0) 82 if (rv > 0)
80 connection_->OnDatagramReceived(&response_, recv_addr_, rv); 83 connection_->OnDatagramReceived(&response_, recv_addr_, rv);
81 84
82 rv = socket_->RecvFrom( 85 rv = socket_->RecvFrom(
83 response_.io_buffer(), 86 response_.io_buffer(), response_.io_buffer()->size(), &recv_addr_,
84 response_.io_buffer()->size(),
85 &recv_addr_,
86 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, 87 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived,
87 base::Unretained(this))); 88 base::Unretained(this)));
88 } while (rv > 0); 89 } while (rv > 0);
89 90
90 if (rv != ERR_IO_PENDING) 91 if (rv != ERR_IO_PENDING)
91 return rv; 92 return rv;
92 93
93 return OK; 94 return OK;
94 } 95 }
95 96
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 189
189 void MDnsConnection::OnDatagramReceived( 190 void MDnsConnection::OnDatagramReceived(
190 DnsResponse* response, 191 DnsResponse* response,
191 const IPEndPoint& recv_addr, 192 const IPEndPoint& recv_addr,
192 int bytes_read) { 193 int bytes_read) {
193 // TODO(noamsml): More sophisticated error handling. 194 // TODO(noamsml): More sophisticated error handling.
194 DCHECK_GT(bytes_read, 0); 195 DCHECK_GT(bytes_read, 0);
195 delegate_->HandlePacket(response, bytes_read); 196 delegate_->HandlePacket(response, bytes_read);
196 } 197 }
197 198
198 MDnsClientImpl::Core::Core() : connection_(new MDnsConnection(this)) { 199 MDnsClientImpl::Core::Core(base::Clock* clock, base::Timer* timer)
200 : clock_(clock),
201 cleanup_timer_(timer),
202 connection_(new MDnsConnection(this)) {
199 } 203 }
200 204
201 MDnsClientImpl::Core::~Core() { 205 MDnsClientImpl::Core::~Core() {
202 STLDeleteValues(&listeners_); 206 STLDeleteValues(&listeners_);
203 } 207 }
204 208
205 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { 209 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) {
206 return connection_->Init(socket_factory); 210 return connection_->Init(socket_factory);
207 } 211 }
208 212
(...skipping 25 matching lines...) Expand all
234 // TODO(noamsml): duplicate query suppression. 238 // TODO(noamsml): duplicate query suppression.
235 if (!(response->flags() & dns_protocol::kFlagResponse)) 239 if (!(response->flags() & dns_protocol::kFlagResponse))
236 return; // Message is a query. ignore it. 240 return; // Message is a query. ignore it.
237 241
238 DnsRecordParser parser = response->Parser(); 242 DnsRecordParser parser = response->Parser();
239 unsigned answer_count = response->answer_count() + 243 unsigned answer_count = response->answer_count() +
240 response->additional_answer_count(); 244 response->additional_answer_count();
241 245
242 for (unsigned i = 0; i < answer_count; i++) { 246 for (unsigned i = 0; i < answer_count; i++) {
243 offset = parser.GetOffset(); 247 offset = parser.GetOffset();
244 scoped_ptr<const RecordParsed> record = RecordParsed::CreateFrom( 248 scoped_ptr<const RecordParsed> record =
245 &parser, base::Time::Now()); 249 RecordParsed::CreateFrom(&parser, clock_->Now());
246 250
247 if (!record) { 251 if (!record) {
248 DVLOG(1) << "Could not understand an mDNS record."; 252 DVLOG(1) << "Could not understand an mDNS record.";
249 253
250 if (offset == parser.GetOffset()) { 254 if (offset == parser.GetOffset()) {
251 DVLOG(1) << "Abandoned parsing the rest of the packet."; 255 DVLOG(1) << "Abandoned parsing the rest of the packet.";
252 return; // The parser did not advance, abort reading the packet. 256 return; // The parser did not advance, abort reading the packet.
253 } else { 257 } else {
254 continue; // We may be able to extract other records from the packet. 258 continue; // We may be able to extract other records from the packet.
255 } 259 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 } 292 }
289 293
290 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { 294 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) {
291 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type()); 295 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type());
292 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>(); 296 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>();
293 DCHECK(rdata); 297 DCHECK(rdata);
294 298
295 // Remove all cached records matching the nonexistent RR types. 299 // Remove all cached records matching the nonexistent RR types.
296 std::vector<const RecordParsed*> records_to_remove; 300 std::vector<const RecordParsed*> records_to_remove;
297 301
298 cache_.FindDnsRecords(0, record->name(), &records_to_remove, 302 cache_.FindDnsRecords(0, record->name(), &records_to_remove, clock_->Now());
299 base::Time::Now());
300 303
301 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); 304 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin();
302 i != records_to_remove.end(); i++) { 305 i != records_to_remove.end(); i++) {
303 if ((*i)->type() == dns_protocol::kTypeNSEC) 306 if ((*i)->type() == dns_protocol::kTypeNSEC)
304 continue; 307 continue;
305 if (!rdata->GetBit((*i)->type())) { 308 if (!rdata->GetBit((*i)->type())) {
306 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i)); 309 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i));
307 DCHECK(record_removed); 310 DCHECK(record_removed);
308 OnRecordRemoved(record_removed.get()); 311 OnRecordRemoved(record_removed.get());
309 } 312 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { 376 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) {
374 ListenerMap::iterator found = listeners_.find(key); 377 ListenerMap::iterator found = listeners_.find(key);
375 if (found != listeners_.end() && !found->second->might_have_observers()) { 378 if (found != listeners_.end() && !found->second->might_have_observers()) {
376 delete found->second; 379 delete found->second;
377 listeners_.erase(found); 380 listeners_.erase(found);
378 } 381 }
379 } 382 }
380 383
381 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { 384 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) {
382 // Cleanup is already scheduled, no need to do anything. 385 // Cleanup is already scheduled, no need to do anything.
383 if (cleanup == scheduled_cleanup_) return; 386 if (cleanup == scheduled_cleanup_) {
387 return;
388 }
384 scheduled_cleanup_ = cleanup; 389 scheduled_cleanup_ = cleanup;
385 390
386 // This cancels the previously scheduled cleanup. 391 // This cancels the previously scheduled cleanup.
387 cleanup_callback_.Reset(base::Bind( 392 cleanup_timer_->Stop();
388 &MDnsClientImpl::Core::DoCleanup, base::Unretained(this)));
389 393
390 // If |cleanup| is empty, then no cleanup necessary. 394 // If |cleanup| is empty, then no cleanup necessary.
391 if (cleanup != base::Time()) { 395 if (cleanup != base::Time()) {
392 base::MessageLoop::current()->PostDelayedTask( 396 cleanup_timer_->Start(
393 FROM_HERE, 397 FROM_HERE, std::max(base::TimeDelta(), cleanup - clock_->Now()),
394 cleanup_callback_.callback(), 398 base::Bind(&MDnsClientImpl::Core::DoCleanup, base::Unretained(this)));
395 cleanup - base::Time::Now());
396 } 399 }
397 } 400 }
398 401
399 void MDnsClientImpl::Core::DoCleanup() { 402 void MDnsClientImpl::Core::DoCleanup() {
400 cache_.CleanupRecords(base::Time::Now(), base::Bind( 403 cache_.CleanupRecords(clock_->Now(),
401 &MDnsClientImpl::Core::OnRecordRemoved, base::Unretained(this))); 404 base::Bind(&MDnsClientImpl::Core::OnRecordRemoved,
405 base::Unretained(this)));
402 406
403 ScheduleCleanup(cache_.next_expiration()); 407 ScheduleCleanup(cache_.next_expiration());
404 } 408 }
405 409
406 void MDnsClientImpl::Core::OnRecordRemoved( 410 void MDnsClientImpl::Core::OnRecordRemoved(
407 const RecordParsed* record) { 411 const RecordParsed* record) {
408 AlertListeners(MDnsCache::RecordRemoved, 412 AlertListeners(MDnsCache::RecordRemoved,
409 ListenerKey(record->name(), record->type()), record); 413 ListenerKey(record->name(), record->type()), record);
410 } 414 }
411 415
412 void MDnsClientImpl::Core::QueryCache( 416 void MDnsClientImpl::Core::QueryCache(
413 uint16 rrtype, const std::string& name, 417 uint16 rrtype, const std::string& name,
414 std::vector<const RecordParsed*>* records) const { 418 std::vector<const RecordParsed*>* records) const {
415 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); 419 cache_.FindDnsRecords(rrtype, name, records, clock_->Now());
416 } 420 }
417 421
418 MDnsClientImpl::MDnsClientImpl() { 422 MDnsClientImpl::MDnsClientImpl()
423 : clock_(new base::DefaultClock),
424 cleanup_timer_(new base::Timer(false, false)) {
425 }
426
427 MDnsClientImpl::MDnsClientImpl(scoped_ptr<base::Clock> clock,
428 scoped_ptr<base::Timer> timer)
429 : clock_(clock.Pass()), cleanup_timer_(timer.Pass()) {
419 } 430 }
420 431
421 MDnsClientImpl::~MDnsClientImpl() { 432 MDnsClientImpl::~MDnsClientImpl() {
422 } 433 }
423 434
424 bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) { 435 bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) {
425 DCHECK(!core_.get()); 436 DCHECK(!core_.get());
426 core_.reset(new Core()); 437 core_.reset(new Core(clock_.get(), cleanup_timer_.get()));
427 if (!core_->Init(socket_factory)) { 438 if (!core_->Init(socket_factory)) {
428 core_.reset(); 439 core_.reset();
429 return false; 440 return false;
430 } 441 }
431 return true; 442 return true;
432 } 443 }
433 444
434 void MDnsClientImpl::StopListening() { 445 void MDnsClientImpl::StopListening() {
435 core_.reset(); 446 core_.reset();
436 } 447 }
437 448
438 bool MDnsClientImpl::IsListening() const { 449 bool MDnsClientImpl::IsListening() const {
439 return core_.get() != NULL; 450 return core_.get() != NULL;
440 } 451 }
441 452
442 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( 453 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener(
443 uint16 rrtype, 454 uint16 rrtype,
444 const std::string& name, 455 const std::string& name,
445 MDnsListener::Delegate* delegate) { 456 MDnsListener::Delegate* delegate) {
446 return scoped_ptr<net::MDnsListener>( 457 return scoped_ptr<net::MDnsListener>(
447 new MDnsListenerImpl(rrtype, name, delegate, this)); 458 new MDnsListenerImpl(rrtype, name, clock_.get(), delegate, this));
448 } 459 }
449 460
450 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( 461 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction(
451 uint16 rrtype, 462 uint16 rrtype,
452 const std::string& name, 463 const std::string& name,
453 int flags, 464 int flags,
454 const MDnsTransaction::ResultCallback& callback) { 465 const MDnsTransaction::ResultCallback& callback) {
455 return scoped_ptr<MDnsTransaction>( 466 return scoped_ptr<MDnsTransaction>(
456 new MDnsTransactionImpl(rrtype, name, flags, callback, this)); 467 new MDnsTransactionImpl(rrtype, name, flags, callback, this));
457 } 468 }
458 469
459 MDnsListenerImpl::MDnsListenerImpl( 470 MDnsListenerImpl::MDnsListenerImpl(
460 uint16 rrtype, 471 uint16 rrtype,
461 const std::string& name, 472 const std::string& name,
473 base::Clock* clock,
462 MDnsListener::Delegate* delegate, 474 MDnsListener::Delegate* delegate,
463 MDnsClientImpl* client) 475 MDnsClientImpl* client)
464 : rrtype_(rrtype), name_(name), client_(client), delegate_(delegate), 476 : rrtype_(rrtype), name_(name), clock_(clock), client_(client),
465 started_(false), active_refresh_(false) { 477 delegate_(delegate), started_(false), active_refresh_(false) {
466 } 478 }
467 479
468 MDnsListenerImpl::~MDnsListenerImpl() { 480 MDnsListenerImpl::~MDnsListenerImpl() {
469 if (started_) { 481 if (started_) {
470 DCHECK(client_->core()); 482 DCHECK(client_->core());
471 client_->core()->RemoveListener(this); 483 client_->core()->RemoveListener(this);
472 } 484 }
473 } 485 }
474 486
475 bool MDnsListenerImpl::Start() { 487 bool MDnsListenerImpl::Start() {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 static_cast<int>(base::Time::kMillisecondsPerSecond * 578 static_cast<int>(base::Time::kMillisecondsPerSecond *
567 kListenerRefreshRatio1 * ttl_)); 579 kListenerRefreshRatio1 * ttl_));
568 580
569 base::Time next_refresh2 = last_update_ + base::TimeDelta::FromMilliseconds( 581 base::Time next_refresh2 = last_update_ + base::TimeDelta::FromMilliseconds(
570 static_cast<int>(base::Time::kMillisecondsPerSecond * 582 static_cast<int>(base::Time::kMillisecondsPerSecond *
571 kListenerRefreshRatio2 * ttl_)); 583 kListenerRefreshRatio2 * ttl_));
572 584
573 base::MessageLoop::current()->PostDelayedTask( 585 base::MessageLoop::current()->PostDelayedTask(
574 FROM_HERE, 586 FROM_HERE,
575 next_refresh_.callback(), 587 next_refresh_.callback(),
576 next_refresh1 - base::Time::Now()); 588 next_refresh1 - clock_->Now());
577 589
578 base::MessageLoop::current()->PostDelayedTask( 590 base::MessageLoop::current()->PostDelayedTask(
579 FROM_HERE, 591 FROM_HERE,
580 next_refresh_.callback(), 592 next_refresh_.callback(),
581 next_refresh2 - base::Time::Now()); 593 next_refresh2 - clock_->Now());
582 } 594 }
583 595
584 void MDnsListenerImpl::DoRefresh() { 596 void MDnsListenerImpl::DoRefresh() {
585 client_->core()->SendQuery(rrtype_, name_); 597 client_->core()->SendQuery(rrtype_, name_);
586 } 598 }
587 599
588 MDnsTransactionImpl::MDnsTransactionImpl( 600 MDnsTransactionImpl::MDnsTransactionImpl(
589 uint16 rrtype, 601 uint16 rrtype,
590 const std::string& name, 602 const std::string& name,
591 int flags, 603 int flags,
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 738
727 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { 739 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) {
728 TriggerCallback(RESULT_NSEC, NULL); 740 TriggerCallback(RESULT_NSEC, NULL);
729 } 741 }
730 742
731 void MDnsTransactionImpl::OnCachePurged() { 743 void MDnsTransactionImpl::OnCachePurged() {
732 // TODO(noamsml): Cache purge situations not yet implemented 744 // TODO(noamsml): Cache purge situations not yet implemented
733 } 745 }
734 746
735 } // namespace net 747 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698