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

Unified Diff: net/dns/mdns_client_impl.cc

Issue 15733008: Multicast DNS implementation (initial) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mdns_implementation2
Patch Set: Created 7 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: net/dns/mdns_client_impl.cc
diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc
index 2c6da79ed988b694a61b096f7203d4e0d44bda72..900046eba0c68b7e0917448f65e619c3ff428d9a 100644
--- a/net/dns/mdns_client_impl.cc
+++ b/net/dns/mdns_client_impl.cc
@@ -13,15 +13,14 @@
#include "net/base/net_log.h"
#include "net/base/rand_callback.h"
#include "net/dns/dns_protocol.h"
-#include "net/dns/mdns_query.h"
#include "net/udp/datagram_socket.h"
namespace net {
-static const char kMDNSMulticastGroupIPv4[] = "224.0.0.251";
-static const char kMDNSMulticastGroupIPv6[] = "FF02::FB";
+static const char kMDnsMulticastGroupIPv4[] = "224.0.0.251";
+static const char kMDnsMulticastGroupIPv6[] = "FF02::FB";
-static const unsigned kMDnsTransactionTimeoutSeconds = 3;
+static const unsigned kMDnsTransactionNoResultsSeconds = 3;
MDnsClientImpl::Core::Core(MDnsClientImpl* client,
MDnsConnectionFactory* connection_factory)
@@ -34,7 +33,7 @@ MDnsClientImpl::Core::~Core() {
}
bool MDnsClientImpl::Core::Init() {
- return connection_->Init();
+ return connection_->Init() == OK;
}
bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) {
@@ -42,11 +41,10 @@ bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) {
if (!DNSDomainFromDot(name, &name_dns))
return false;
- MDnsQuery query(name_dns, rrtype);
+ // TODO(noamsml): Remove RD flag from query and add known-answer suppression.
+ DnsQuery query(0, name_dns, rrtype);
- connection_->Send(query.io_buffer(), query.size());
-
- return true;
+ return connection_->Send(query.io_buffer(), query.io_buffer()->size()) == OK;
}
void MDnsClientImpl::Core::HandlePacket(DnsResponse* response,
@@ -121,6 +119,10 @@ void MDnsClientImpl::Core::HandlePacket(DnsResponse* response,
}
}
+void MDnsClientImpl::Core::OnConnectionError(int error) {
+ // TODO(noamsml): On connection error, recreate connection and flush cache.
+}
+
void MDnsClientImpl::Core::AlertListeners(
MDnsUpdateType update_type,
const ListenerKey& key,
@@ -133,7 +135,7 @@ void MDnsClientImpl::Core::AlertListeners(
}
void MDnsClientImpl::Core::AddListener(
- MDnsListenerImpl* listener, bool alert_existing_records) {
+ MDnsListenerImpl* listener) {
ListenerKey key(listener->GetType(), listener->GetName());
std::pair<ListenerMap::iterator, bool> observer_insert_result =
listeners_.insert(
@@ -148,22 +150,6 @@ void MDnsClientImpl::Core::AddListener(
observer_insert_result.first->second;
observer_list->AddObserver(listener);
-
- if (alert_existing_records) {
- std::vector<const RecordParsed*> records;
-
- cache_.FindDnsRecords(listener->GetType(), listener->GetName(),
- &records, base::Time::Now());
-
- base::WeakPtr<MDnsListenerImpl> weak_listener = listener->AsWeakPtr();
-
- for (std::vector<const RecordParsed*>::iterator i = records.begin();
- i != records.end(); i++) {
- if (weak_listener) {
- weak_listener->AlertDelegate(kMDnsRecordAdded, *i);
- }
- }
- }
}
void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) {
@@ -269,32 +255,27 @@ bool MDnsClientImpl::IsListeningForTests() {
scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener(
uint16 rrtype,
const std::string& name,
- bool active,
- bool alert_existing_records,
MDnsListener::Delegate* delegate) {
return scoped_ptr<net::MDnsListener>(
- new MDnsListenerImpl(rrtype, name, active, alert_existing_records,
- delegate, this));
+ new MDnsListenerImpl(rrtype, name, delegate, this));
}
scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction(
uint16 rrtype,
const std::string& name,
+ int flags,
const MDnsTransaction::ResultCallback& callback) {
return scoped_ptr<MDnsTransaction>(
- new MDnsTransactionImpl(rrtype, name, callback, this));
+ new MDnsTransactionImpl(rrtype, name, flags, callback, this));
}
MDnsListenerImpl::MDnsListenerImpl(
uint16 rrtype,
const std::string& name,
- bool active,
- bool alert_existing_records,
MDnsListener::Delegate* delegate,
MDnsClientImpl* client)
- : rrtype_(rrtype), name_(name), active_(active),
- alert_existing_records_(alert_existing_records), client_(client),
- delegate_(delegate), started_(false) {
+ : rrtype_(rrtype), name_(name), client_(client), delegate_(delegate),
+ started_(false) {
}
bool MDnsListenerImpl::Start() {
@@ -303,9 +284,8 @@ bool MDnsListenerImpl::Start() {
if (!client_->AddListenRef()) return false;
started_ = true;
- client_->core()->AddListener(this, alert_existing_records_);
+ client_->core()->AddListener(this);
- if (active_) SendQuery(false); // TODO(noamsml): Retry logic.
return true;
}
@@ -324,25 +304,6 @@ uint16 MDnsListenerImpl::GetType() const {
return rrtype_;
}
-bool MDnsListenerImpl::IsActive() const {
- return active_;
-}
-
-bool MDnsListenerImpl::SendQuery(bool force_refresh_cache) {
- DCHECK(started_);
- // TODO(noamsml): Logic related to force_refresh_cache
- if (name_.size() == 0) return false;
- return client_->core()->SendQuery(rrtype_, name_);
-}
-
-bool MDnsListenerImpl::QueryCache(
- std::vector<const RecordParsed*>* records) const {
- DCHECK(started_);
- if (name_.size() == 0) return false;
- client_->core()->QueryCache(rrtype_, name_, records);
- return true;
-}
-
void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type,
const RecordParsed* record) {
DCHECK(started_);
@@ -352,38 +313,62 @@ void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type,
MDnsTransactionImpl::MDnsTransactionImpl(
uint16 rrtype,
const std::string& name,
+ int flags,
const MDnsTransaction::ResultCallback& callback,
MDnsClientImpl* client)
: rrtype_(rrtype), name_(name), callback_(callback), client_(client),
- started_(false) {
+ started_(false), flags_(flags) {
+ DCHECK((flags_ & kMDnsTransactionFlagMask) == flags_);
+ DCHECK(flags_ & kMDnsTransactionQueryCache ||
+ flags_ & kMDnsTransactionQueryNetwork);
}
MDnsTransactionImpl::~MDnsTransactionImpl() {
+ timeout_.Cancel();
}
bool MDnsTransactionImpl::Start() {
DCHECK(!started_);
started_ = true;
std::vector<const RecordParsed*> records;
- if (client_->core()) {
- client_->core()->QueryCache(rrtype_, name_, &records);
- if (!records.empty()) {
- TriggerCallback(kMDnsTransactionSuccess, records.front());
- return true;
+ base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr();
+
+ if (flags_ & kMDnsTransactionQueryCache) {
+ if (client_->core()) {
+ client_->core()->QueryCache(rrtype_, name_, &records);
+ for (std::vector<const RecordParsed*>::iterator i = records.begin();
+ i != records.end() && weak_this; ++i) {
+ weak_this->TriggerCallback(kMDnsTransactionRecord, records.front());
+ }
}
}
- listener_ = client_->CreateListener(rrtype_, name_, true /*active*/,
- false /*alert existing*/, this);
- listener_->Start();
+ if (!weak_this) return true;
+
+ if (is_active() && flags_ & kMDnsTransactionQueryNetwork) {
+ listener_ = client_->CreateListener(rrtype_, name_, this);
+ if (!listener_->Start()) return false;
+
+ DCHECK(client_->core());
+ if (!client_->core()->SendQuery(rrtype_, name_)) {
+ return false;
+ }
- timeout_.Reset(base::Bind(&MDnsTransactionImpl::OnTimedOut, AsWeakPtr()));
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- timeout_.callback(),
- base::TimeDelta::FromSeconds(kMDnsTransactionTimeoutSeconds));
+ timeout_.Reset(base::Bind(&MDnsTransactionImpl::SignalTransactionOver,
+ weak_this));
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ timeout_.callback(),
+ base::TimeDelta::FromSeconds(kMDnsTransactionNoResultsSeconds));
+
+ return listener_.get() != NULL;
+ } else {
+ // If this is a cache only query, signal that the transaction is over
+ // immediately.
+ SignalTransactionOver();
+ }
- return listener_.get() != NULL;
+ return true;
}
const std::string& MDnsTransactionImpl::GetName() const {
@@ -402,46 +387,86 @@ void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) {
void MDnsTransactionImpl::TriggerCallback(MDnsTransactionResult result,
const RecordParsed* record) {
DCHECK(started_);
- if (callback_.is_null()) return;
+ if (!is_active()) return;
// Ensure callback is run after touching all class state, so that
// the callback can delete the transaction.
MDnsTransaction::ResultCallback callback = callback_;
+ if (flags_ & kMDnsTransactionSingleResult) {
+ Reset();
+ }
+
+ callback.Run(result, record);
+}
+
+void MDnsTransactionImpl::Reset() {
callback_.Reset();
listener_.reset();
timeout_.Cancel();
-
- callback.Run(result, record);
}
void MDnsTransactionImpl::OnRecordUpdate(MDnsUpdateType update,
const RecordParsed* record) {
DCHECK(started_);
if (update == kMDnsRecordAdded || update == kMDnsRecordChanged) {
- TriggerCallback(kMDnsTransactionSuccess, record);
+ TriggerCallback(kMDnsTransactionRecord, record);
}
}
-void MDnsTransactionImpl::OnTimedOut() {
+void MDnsTransactionImpl::SignalTransactionOver() {
DCHECK(started_);
- TriggerCallback(kMDnsTransactionTimeout, NULL);
+ base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr();
+
+ if (flags_ & kMDnsTransactionSingleResult) {
+ TriggerCallback(kMDnsTransactionNoResults, NULL);
+ } else {
+ TriggerCallback(kMDnsTransactionDone, NULL);
+ }
+
+ if (weak_this) {
+ weak_this->Reset();
+ }
}
void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) {
// TODO(noamsml): NSEC records not yet implemented
}
-MDnsConnectionImpl::RecvLoop::RecvLoop(
- DatagramServerSocket* socket, MDnsConnectionImpl* connection)
+void MDnsTransactionImpl::OnCachePurged() {
+ // TODO(noamsml): Cache purge situations not yet implemented
+}
+
+MDnsConnectionImpl::SocketHandler::SocketHandler(
+ MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr)
+ : socket_owned_(new UDPServerSocket(NULL, NetLog::Source())),
+ socket_(socket_owned_.get()), connection_(connection),
+ response_(new DnsResponse(dns_protocol::kMaxMulticastSize)),
+ multicast_addr_(multicast_addr) {
+}
+
+MDnsConnectionImpl::SocketHandler::SocketHandler(
+ DatagramServerSocket* socket,
+ MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr)
: socket_(socket), connection_(connection),
- response_(new DnsResponse(dns_protocol::kMaxMulticastSize)) {
+ response_(new DnsResponse(dns_protocol::kMaxMulticastSize)),
+ multicast_addr_(multicast_addr) {
+}
+
+
+MDnsConnectionImpl::SocketHandler::~SocketHandler() {
}
-MDnsConnectionImpl::RecvLoop::~RecvLoop() {
+int MDnsConnectionImpl::SocketHandler::Start() {
+ int rv = BindSocket();
+ if (rv != OK) {
+ return rv;
+ }
+
+ return DoLoop(0);
}
-void MDnsConnectionImpl::RecvLoop::DoLoop(int rv) {
+int MDnsConnectionImpl::SocketHandler::DoLoop(int rv) {
do {
if (rv > 0) {
connection_->OnDatagramReceived(socket_,
@@ -452,124 +477,114 @@ void MDnsConnectionImpl::RecvLoop::DoLoop(int rv) {
response_->io_buffer(),
response_->io_buffer()->size(),
&recv_addr_,
- base::Bind(&MDnsConnectionImpl::RecvLoop::OnDatagramReceived,
+ base::Bind(&MDnsConnectionImpl::SocketHandler::OnDatagramReceived,
base::Unretained(this)));
} while (rv > 0);
if (rv != ERR_IO_PENDING) {
- connection_->OnError(this, socket_, rv);
+ return rv;
}
-}
-void MDnsConnectionImpl::RecvLoop::OnDatagramReceived(int rv) {
- DoLoop(rv);
+ return OK;
}
-MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate)
- : socket_ipv4_(new UDPServerSocket(NULL, NetLog::Source())),
- socket_ipv6_(new UDPServerSocket(NULL, NetLog::Source())),
- loop_ipv4_(socket_ipv4_.get(), this),
- loop_ipv6_(socket_ipv6_.get(), this),
- delegate_(delegate) {
+void MDnsConnectionImpl::SocketHandler::OnDatagramReceived(int rv) {
+ if (rv >= OK) {
+ rv = DoLoop(rv);
+ }
+
+ if (rv != OK) {
+ connection_->OnError(this, rv);
+ }
}
-MDnsConnectionImpl::~MDnsConnectionImpl() {
- socket_ipv4_->Close();
- socket_ipv6_->Close();
+int MDnsConnectionImpl::SocketHandler::Send(IOBuffer* buffer, unsigned size) {
+ return socket_->SendTo(
+ buffer, size, multicast_addr_,
+ base::Bind(&MDnsConnectionImpl::SocketHandler::SendDone,
+ base::Unretained(this) ));
}
-bool MDnsConnectionImpl::Init() {
- if (!BindSocket(socket_ipv4_.get(), kIPv4AddressSize,
- kMDNSMulticastGroupIPv4))
- return false;
+void MDnsConnectionImpl::SocketHandler::SendDone(int sent) {
+ // TODO(noamsml): Retry logic.
+}
- if (!BindSocket(socket_ipv6_.get(), kIPv6AddressSize,
- kMDNSMulticastGroupIPv6))
- return false;
+int MDnsConnectionImpl::SocketHandler::BindSocket() {
+ IPAddressNumber address_any;
+ address_any.resize(multicast_addr_.address().size(), 0);
- loop_ipv4_.DoLoop(0);
- loop_ipv6_.DoLoop(0);
+ IPEndPoint bind_endpoint(address_any, multicast_addr_.port());
- return true;
-}
+ socket_->AllowAddressReuse();
+ int rv = socket_->Listen(bind_endpoint);
-bool MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) {
- int rv = socket_ipv4_->SendTo(
- buffer,
- size,
- GetIPv4SendEndpoint(),
- base::Bind(&MDnsConnectionImpl::SendDone,
- base::Unretained(this) ));
- if (rv < OK && rv != ERR_IO_PENDING) return false;
+ if (rv < OK) return rv;
- rv = socket_ipv6_->SendTo(
- buffer,
- size,
- GetIPv6SendEndpoint(),
- base::Bind(&MDnsConnectionImpl::SendDone,
- base::Unretained(this) ));
- if (rv < OK && rv != ERR_IO_PENDING) return false;
+ socket_->SetMulticastLoopbackMode(false);
- return true;
+ return socket_->JoinGroup(multicast_addr_.address());
}
-void MDnsConnectionImpl::SendDone(int sent) {
- // TODO(noamsml): Queueing and retry logic.
+
+MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate)
+ : socket_handler_ipv4_(this, GetIPEndPoint(kMDnsMulticastGroupIPv4,
szym 2013/06/10 21:58:28 If you always use this with the same port, why not
Noam Samuel 2013/06/11 20:35:03 Done.
+ dns_protocol::kDefaultPortMulticast)),
+ socket_handler_ipv6_(this, GetIPEndPoint(kMDnsMulticastGroupIPv6,
+ dns_protocol::kDefaultPortMulticast)),
+ delegate_(delegate) {
}
-void MDnsConnectionImpl::OnError(RecvLoop* loop,
- DatagramServerSocket* socket,
- int error) {
- // TODO(noamsml): Error handling.
+MDnsConnectionImpl::MDnsConnectionImpl(DatagramServerSocket* socket_ipv4,
+ DatagramServerSocket* socket_ipv6,
+ MDnsConnection::Delegate* delegate)
+ : socket_handler_ipv4_(socket_ipv4, this,
+ GetIPEndPoint(kMDnsMulticastGroupIPv4,
+ dns_protocol::kDefaultPortMulticast)),
+ socket_handler_ipv6_(socket_ipv6, this,
+ GetIPEndPoint(kMDnsMulticastGroupIPv6,
+ dns_protocol::kDefaultPortMulticast)),
+ delegate_(delegate) {
}
-bool MDnsConnectionImpl::BindSocket(
- DatagramServerSocket* socket,
- int addr_size,
- const char* multicast_group) {
- IPAddressNumber address_any;
- address_any.resize(addr_size, 0);
+MDnsConnectionImpl::~MDnsConnectionImpl() {
+}
- IPAddressNumber multicast_group_number;
+int MDnsConnectionImpl::Init() {
+ int rv;
- IPEndPoint bind_endpoint(address_any, dns_protocol::kDefaultPortMulticast);
+ rv = socket_handler_ipv4_.Start();
+ if (rv != OK) return rv;
+ rv = socket_handler_ipv6_.Start();
+ if (rv != OK) return rv;
- bool success = ParseIPLiteralToNumber(multicast_group,
- &multicast_group_number);
- DCHECK(success);
-
- socket->AllowAddressReuse();
- int status = socket->Listen(bind_endpoint);
-
- if (status < 0)
- return false;
+ return true;
+}
- socket->SetMulticastLoopbackMode(false);
+int MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) {
+ int rv;
- status = socket->JoinGroup(multicast_group_number);
+ rv = socket_handler_ipv4_.Send(buffer, size);
+ if (rv < OK && rv != ERR_IO_PENDING) return rv;
- if (status < 0)
- return false;
+ rv = socket_handler_ipv6_.Send(buffer, size);
+ if (rv < OK && rv != ERR_IO_PENDING) return rv;
- return true;
+ return OK;
}
-IPEndPoint MDnsConnectionImpl::GetIPv4SendEndpoint() {
- IPAddressNumber multicast_group_number;
- bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv4,
- &multicast_group_number);
- DCHECK(success);
- return IPEndPoint(multicast_group_number,
- dns_protocol::kDefaultPortMulticast);
+void MDnsConnectionImpl::OnError(SocketHandler* loop,
+ int error) {
+ // TODO(noamsml): Specific handling of intermittent errors that can be handled
+ // in the connection.
+ delegate_->OnConnectionError(error);
}
-IPEndPoint MDnsConnectionImpl::GetIPv6SendEndpoint() {
+IPEndPoint MDnsConnectionImpl::GetIPEndPoint(const char* address, int port) {
IPAddressNumber multicast_group_number;
- bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv6,
+ bool success = ParseIPLiteralToNumber(address,
&multicast_group_number);
DCHECK(success);
- return IPEndPoint(multicast_group_number,
- dns_protocol::kDefaultPortMulticast);
+ return IPEndPoint(multicast_group_number, port);
}
void MDnsConnectionImpl::OnDatagramReceived(

Powered by Google App Engine
This is Rietveld 408576698