Commit 3e740be5 authored by kmarshall's avatar kmarshall Committed by Commit bot

Fix MDnsClient's cache entry cleanup logic.

The current implementation has an error in its time delay computation.
It computes negative timedeltas for cache entries that are
> Now(). This causes a CHECK failure in
IncomingTaskQueue::CalculateDelayedRuntime.

BUG=459443
CC=mfoltz@chromium.org

Review URL: https://codereview.chromium.org/937743003

Cr-Commit-Position: refs/heads/master@{#318766}
parent 6c6d81a4
...@@ -4,13 +4,16 @@ ...@@ -4,13 +4,16 @@
#include "net/dns/mdns_client_impl.h" #include "net/dns/mdns_client_impl.h"
#include <algorithm>
#include <queue> #include <queue>
#include "base/bind.h" #include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h" #include "base/time/default_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/dns_util.h" #include "net/base/dns_util.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/net_log.h" #include "net/base/net_log.h"
...@@ -80,9 +83,7 @@ int MDnsConnection::SocketHandler::DoLoop(int rv) { ...@@ -80,9 +83,7 @@ int MDnsConnection::SocketHandler::DoLoop(int rv) {
connection_->OnDatagramReceived(&response_, recv_addr_, rv); connection_->OnDatagramReceived(&response_, recv_addr_, rv);
rv = socket_->RecvFrom( rv = socket_->RecvFrom(
response_.io_buffer(), response_.io_buffer(), response_.io_buffer()->size(), &recv_addr_,
response_.io_buffer()->size(),
&recv_addr_,
base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived,
base::Unretained(this))); base::Unretained(this)));
} while (rv > 0); } while (rv > 0);
...@@ -195,7 +196,10 @@ void MDnsConnection::OnDatagramReceived( ...@@ -195,7 +196,10 @@ void MDnsConnection::OnDatagramReceived(
delegate_->HandlePacket(response, bytes_read); delegate_->HandlePacket(response, bytes_read);
} }
MDnsClientImpl::Core::Core() : connection_(new MDnsConnection(this)) { MDnsClientImpl::Core::Core(base::Clock* clock, base::Timer* timer)
: clock_(clock),
cleanup_timer_(timer),
connection_(new MDnsConnection(this)) {
} }
MDnsClientImpl::Core::~Core() { MDnsClientImpl::Core::~Core() {
...@@ -241,8 +245,8 @@ void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, ...@@ -241,8 +245,8 @@ void MDnsClientImpl::Core::HandlePacket(DnsResponse* response,
for (unsigned i = 0; i < answer_count; i++) { for (unsigned i = 0; i < answer_count; i++) {
offset = parser.GetOffset(); offset = parser.GetOffset();
scoped_ptr<const RecordParsed> record = RecordParsed::CreateFrom( scoped_ptr<const RecordParsed> record =
&parser, base::Time::Now()); RecordParsed::CreateFrom(&parser, clock_->Now());
if (!record) { if (!record) {
DVLOG(1) << "Could not understand an mDNS record."; DVLOG(1) << "Could not understand an mDNS record.";
...@@ -295,8 +299,7 @@ void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { ...@@ -295,8 +299,7 @@ void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) {
// Remove all cached records matching the nonexistent RR types. // Remove all cached records matching the nonexistent RR types.
std::vector<const RecordParsed*> records_to_remove; std::vector<const RecordParsed*> records_to_remove;
cache_.FindDnsRecords(0, record->name(), &records_to_remove, cache_.FindDnsRecords(0, record->name(), &records_to_remove, clock_->Now());
base::Time::Now());
for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin();
i != records_to_remove.end(); i++) { i != records_to_remove.end(); i++) {
...@@ -380,25 +383,26 @@ void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { ...@@ -380,25 +383,26 @@ void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) {
void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) {
// Cleanup is already scheduled, no need to do anything. // Cleanup is already scheduled, no need to do anything.
if (cleanup == scheduled_cleanup_) return; if (cleanup == scheduled_cleanup_) {
return;
}
scheduled_cleanup_ = cleanup; scheduled_cleanup_ = cleanup;
// This cancels the previously scheduled cleanup. // This cancels the previously scheduled cleanup.
cleanup_callback_.Reset(base::Bind( cleanup_timer_->Stop();
&MDnsClientImpl::Core::DoCleanup, base::Unretained(this)));
// If |cleanup| is empty, then no cleanup necessary. // If |cleanup| is empty, then no cleanup necessary.
if (cleanup != base::Time()) { if (cleanup != base::Time()) {
base::MessageLoop::current()->PostDelayedTask( cleanup_timer_->Start(
FROM_HERE, FROM_HERE, std::max(base::TimeDelta(), cleanup - clock_->Now()),
cleanup_callback_.callback(), base::Bind(&MDnsClientImpl::Core::DoCleanup, base::Unretained(this)));
cleanup - base::Time::Now());
} }
} }
void MDnsClientImpl::Core::DoCleanup() { void MDnsClientImpl::Core::DoCleanup() {
cache_.CleanupRecords(base::Time::Now(), base::Bind( cache_.CleanupRecords(clock_->Now(),
&MDnsClientImpl::Core::OnRecordRemoved, base::Unretained(this))); base::Bind(&MDnsClientImpl::Core::OnRecordRemoved,
base::Unretained(this)));
ScheduleCleanup(cache_.next_expiration()); ScheduleCleanup(cache_.next_expiration());
} }
...@@ -412,10 +416,17 @@ void MDnsClientImpl::Core::OnRecordRemoved( ...@@ -412,10 +416,17 @@ void MDnsClientImpl::Core::OnRecordRemoved(
void MDnsClientImpl::Core::QueryCache( void MDnsClientImpl::Core::QueryCache(
uint16 rrtype, const std::string& name, uint16 rrtype, const std::string& name,
std::vector<const RecordParsed*>* records) const { std::vector<const RecordParsed*>* records) const {
cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); cache_.FindDnsRecords(rrtype, name, records, clock_->Now());
} }
MDnsClientImpl::MDnsClientImpl() { MDnsClientImpl::MDnsClientImpl()
: clock_(new base::DefaultClock),
cleanup_timer_(new base::Timer(false, false)) {
}
MDnsClientImpl::MDnsClientImpl(scoped_ptr<base::Clock> clock,
scoped_ptr<base::Timer> timer)
: clock_(clock.Pass()), cleanup_timer_(timer.Pass()) {
} }
MDnsClientImpl::~MDnsClientImpl() { MDnsClientImpl::~MDnsClientImpl() {
...@@ -423,7 +434,7 @@ MDnsClientImpl::~MDnsClientImpl() { ...@@ -423,7 +434,7 @@ MDnsClientImpl::~MDnsClientImpl() {
bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) { bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) {
DCHECK(!core_.get()); DCHECK(!core_.get());
core_.reset(new Core()); core_.reset(new Core(clock_.get(), cleanup_timer_.get()));
if (!core_->Init(socket_factory)) { if (!core_->Init(socket_factory)) {
core_.reset(); core_.reset();
return false; return false;
...@@ -444,7 +455,7 @@ scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( ...@@ -444,7 +455,7 @@ scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener(
const std::string& name, const std::string& name,
MDnsListener::Delegate* delegate) { MDnsListener::Delegate* delegate) {
return scoped_ptr<net::MDnsListener>( return scoped_ptr<net::MDnsListener>(
new MDnsListenerImpl(rrtype, name, delegate, this)); new MDnsListenerImpl(rrtype, name, clock_.get(), delegate, this));
} }
scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction(
...@@ -456,13 +467,18 @@ scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( ...@@ -456,13 +467,18 @@ scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction(
new MDnsTransactionImpl(rrtype, name, flags, callback, this)); new MDnsTransactionImpl(rrtype, name, flags, callback, this));
} }
MDnsListenerImpl::MDnsListenerImpl( MDnsListenerImpl::MDnsListenerImpl(uint16 rrtype,
uint16 rrtype, const std::string& name,
const std::string& name, base::Clock* clock,
MDnsListener::Delegate* delegate, MDnsListener::Delegate* delegate,
MDnsClientImpl* client) MDnsClientImpl* client)
: rrtype_(rrtype), name_(name), client_(client), delegate_(delegate), : rrtype_(rrtype),
started_(false), active_refresh_(false) { name_(name),
clock_(clock),
client_(client),
delegate_(delegate),
started_(false),
active_refresh_(false) {
} }
MDnsListenerImpl::~MDnsListenerImpl() { MDnsListenerImpl::~MDnsListenerImpl() {
...@@ -571,14 +587,10 @@ void MDnsListenerImpl::ScheduleNextRefresh() { ...@@ -571,14 +587,10 @@ void MDnsListenerImpl::ScheduleNextRefresh() {
kListenerRefreshRatio2 * ttl_)); kListenerRefreshRatio2 * ttl_));
base::MessageLoop::current()->PostDelayedTask( base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, FROM_HERE, next_refresh_.callback(), next_refresh1 - clock_->Now());
next_refresh_.callback(),
next_refresh1 - base::Time::Now());
base::MessageLoop::current()->PostDelayedTask( base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, FROM_HERE, next_refresh_.callback(), next_refresh2 - clock_->Now());
next_refresh_.callback(),
next_refresh2 - base::Time::Now());
} }
void MDnsListenerImpl::DoRefresh() { void MDnsListenerImpl::DoRefresh() {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define NET_DNS_MDNS_CLIENT_IMPL_H_ #define NET_DNS_MDNS_CLIENT_IMPL_H_
#include <map> #include <map>
#include <queue>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -21,11 +22,16 @@ ...@@ -21,11 +22,16 @@
#include "net/udp/udp_server_socket.h" #include "net/udp/udp_server_socket.h"
#include "net/udp/udp_socket.h" #include "net/udp/udp_socket.h"
namespace base {
class Clock;
class Timer;
} // namespace base
namespace net { namespace net {
class MDnsSocketFactoryImpl : public MDnsSocketFactory { class MDnsSocketFactoryImpl : public MDnsSocketFactory {
public: public:
MDnsSocketFactoryImpl() {}; MDnsSocketFactoryImpl() {}
~MDnsSocketFactoryImpl() override{}; ~MDnsSocketFactoryImpl() override{};
void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) override; void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) override;
...@@ -109,7 +115,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { ...@@ -109,7 +115,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
// invalidate the core. // invalidate the core.
class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate { class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate {
public: public:
Core(); Core(base::Clock* clock, base::Timer* timer);
~Core() override; ~Core() override;
// Initialize the core. Returns true on success. // Initialize the core. Returns true on success.
...@@ -132,6 +138,8 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { ...@@ -132,6 +138,8 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
void OnConnectionError(int error) override; void OnConnectionError(int error) override;
private: private:
FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
typedef std::pair<std::string, uint16> ListenerKey; typedef std::pair<std::string, uint16> ListenerKey;
typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* > typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* >
ListenerMap; ListenerMap;
...@@ -159,7 +167,8 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { ...@@ -159,7 +167,8 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
MDnsCache cache_; MDnsCache cache_;
base::CancelableClosure cleanup_callback_; base::Clock* clock_;
base::Timer* cleanup_timer_;
base::Time scheduled_cleanup_; base::Time scheduled_cleanup_;
scoped_ptr<MDnsConnection> connection_; scoped_ptr<MDnsConnection> connection_;
...@@ -189,7 +198,15 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { ...@@ -189,7 +198,15 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
Core* core() { return core_.get(); } Core* core() { return core_.get(); }
private: private:
FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
// Test constructor, takes a mock clock and mock timer.
MDnsClientImpl(scoped_ptr<base::Clock> clock,
scoped_ptr<base::Timer> cleanup_timer);
scoped_ptr<Core> core_; scoped_ptr<Core> core_;
scoped_ptr<base::Clock> clock_;
scoped_ptr<base::Timer> cleanup_timer_;
DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl); DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl);
}; };
...@@ -199,6 +216,7 @@ class MDnsListenerImpl : public MDnsListener, ...@@ -199,6 +216,7 @@ class MDnsListenerImpl : public MDnsListener,
public: public:
MDnsListenerImpl(uint16 rrtype, MDnsListenerImpl(uint16 rrtype,
const std::string& name, const std::string& name,
base::Clock* clock,
MDnsListener::Delegate* delegate, MDnsListener::Delegate* delegate,
MDnsClientImpl* client); MDnsClientImpl* client);
...@@ -229,6 +247,7 @@ class MDnsListenerImpl : public MDnsListener, ...@@ -229,6 +247,7 @@ class MDnsListenerImpl : public MDnsListener,
uint16 rrtype_; uint16 rrtype_;
std::string name_; std::string name_;
base::Clock* clock_;
MDnsClientImpl* client_; MDnsClientImpl* client_;
MDnsListener::Delegate* delegate_; MDnsListener::Delegate* delegate_;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment