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

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: Add unit tests; miscellaneous lint fixes 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
« no previous file with comments | « net/dns/mdns_client_impl.h ('k') | net/dns/mdns_client_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/dns/mdns_client_impl.h ('k') | net/dns/mdns_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698