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( |