service_discovery_host_client.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/local_discovery/service_discovery_host_client.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/local_discovery/local_discovery_messages.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/utility_process_host.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/mdns_client.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_descriptor.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_descriptor_posix.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_POSIX 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace local_discovery { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UtilityProcessHost; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketInfoList GetSocketsOnFileThread() { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::InterfaceIndexFamilyList interfaces(net::GetMDnsInterfacesToBind()); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SocketInfoList sockets; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < interfaces.size(); ++i) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 || 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interfaces[i].second == net::ADDRESS_FAMILY_IPV6); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FileDescriptor socket_descriptor( 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CreatePlatformSocket( 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::ConvertAddressFamily(interfaces[i].second), SOCK_DGRAM, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPPROTO_UDP), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, socket_descriptor.fd == net::kInvalidSocket) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Can't create socket, family=" << interfaces[i].second; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_descriptor.fd != net::kInvalidSocket) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalDiscoveryMsg_SocketInfo socket; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket.descriptor = socket_descriptor; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket.interface_index = interfaces[i].first; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket.address_family = interfaces[i].second; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sockets.push_back(socket); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sockets; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_POSIX 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServiceDiscoveryHostClient::ServiceWatcherProxy : public ServiceWatcher { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceWatcherProxy(ServiceDiscoveryHostClient* host, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service_type, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceWatcher::UpdatedCallback& callback) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : host_(host), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_type_(service_type), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(host_->RegisterWatcherCallback(callback)), 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_(false) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ServiceWatcherProxy() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "~ServiceWatcherProxy with id " << id_; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->UnregisterWatcherCallback(id_); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_DestroyWatcher(id_)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Start() OVERRIDE { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ServiceWatcher::Start with id " << id_; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!started_); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_StartWatcher(id_, service_type_)); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = true; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DiscoverNewServices(bool force_update) OVERRIDE { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ServiceWatcher::DiscoverNewServices with id " << id_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(started_); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_DiscoverServices(id_, force_update)); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual std::string GetServiceType() const OVERRIDE { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return service_type_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ServiceDiscoveryHostClient> host_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string service_type_; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64 id_; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServiceDiscoveryHostClient::ServiceResolverProxy 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public ServiceResolver { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceResolverProxy(ServiceDiscoveryHostClient* host, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service_name, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceResolver::ResolveCompleteCallback& callback) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : host_(host), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_name_(service_name), 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(host->RegisterResolverCallback(callback)), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_(false) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ServiceResolverProxy() { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "~ServiceResolverProxy with id " << id_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->UnregisterResolverCallback(id_); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_DestroyResolver(id_)); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void StartResolving() OVERRIDE { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ServiceResolverProxy::StartResolving with id " << id_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!started_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_ResolveService(id_, service_name_)); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = true; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual std::string GetName() const OVERRIDE { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return service_name_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ServiceDiscoveryHostClient> host_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string service_name_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64 id_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServiceDiscoveryHostClient::LocalDomainResolverProxy 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public LocalDomainResolver { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalDomainResolverProxy(ServiceDiscoveryHostClient* host, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::AddressFamily address_family, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocalDomainResolver::IPAddressCallback& callback) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : host_(host), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain_(domain), 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_family_(address_family), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(host->RegisterLocalDomainResolverCallback(callback)), 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_(false) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~LocalDomainResolverProxy() { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "~LocalDomainResolverProxy with id " << id_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->UnregisterLocalDomainResolverCallback(id_); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_DestroyLocalDomainResolver(id_)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Start() OVERRIDE { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "LocalDomainResolverProxy::Start with id " << id_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!started_); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->Send(new LocalDiscoveryMsg_ResolveLocalDomain(id_, domain_, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_family_)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = true; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ServiceDiscoveryHostClient> host_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string domain_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::AddressFamily address_family_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64 id_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceDiscoveryHostClient::ServiceDiscoveryHostClient() : current_id_(0) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_runner_ = base::MessageLoop::current()->message_loop_proxy(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_runner_ = BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceDiscoveryHostClient::~ServiceDiscoveryHostClient() { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_watcher_callbacks_.empty()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_resolver_callbacks_.empty()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(domain_resolver_callbacks_.empty()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ServiceWatcher> ServiceDiscoveryHostClient::CreateServiceWatcher( 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service_type, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceWatcher::UpdatedCallback& callback) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<ServiceWatcher>( 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ServiceWatcherProxy(this, service_type, callback)); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ServiceResolver> ServiceDiscoveryHostClient::CreateServiceResolver( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service_name, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceResolver::ResolveCompleteCallback& callback) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<ServiceResolver>( 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ServiceResolverProxy(this, service_name, callback)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<LocalDomainResolver> 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceDiscoveryHostClient::CreateLocalDomainResolver( 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::AddressFamily address_family, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocalDomainResolver::IPAddressCallback& callback) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<LocalDomainResolver>(new LocalDomainResolverProxy( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, domain, address_family, callback)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceWatcher::UpdatedCallback& callback) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!ContainsKey(service_watcher_callbacks_, current_id_ + 1)); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_watcher_callbacks_[++current_id_] = callback; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_id_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64 ServiceDiscoveryHostClient::RegisterResolverCallback( 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ServiceResolver::ResolveCompleteCallback& callback) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!ContainsKey(service_resolver_callbacks_, current_id_ + 1)); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_resolver_callbacks_[++current_id_] = callback; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_id_; 221} 222 223uint64 ServiceDiscoveryHostClient::RegisterLocalDomainResolverCallback( 224 const LocalDomainResolver::IPAddressCallback& callback) { 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 226 DCHECK(!ContainsKey(domain_resolver_callbacks_, current_id_ + 1)); 227 domain_resolver_callbacks_[++current_id_] = callback; 228 return current_id_; 229} 230 231void ServiceDiscoveryHostClient::UnregisterWatcherCallback(uint64 id) { 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 233 service_watcher_callbacks_.erase(id); 234} 235 236void ServiceDiscoveryHostClient::UnregisterResolverCallback(uint64 id) { 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 238 service_resolver_callbacks_.erase(id); 239} 240 241void ServiceDiscoveryHostClient::UnregisterLocalDomainResolverCallback( 242 uint64 id) { 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 244 domain_resolver_callbacks_.erase(id); 245} 246 247void ServiceDiscoveryHostClient::Start( 248 const base::Closure& error_callback) { 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 250 DCHECK(!utility_host_); 251 DCHECK(error_callback_.is_null()); 252 error_callback_ = error_callback; 253 io_runner_->PostTask( 254 FROM_HERE, 255 base::Bind(&ServiceDiscoveryHostClient::StartOnIOThread, this)); 256} 257 258void ServiceDiscoveryHostClient::Shutdown() { 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 260 io_runner_->PostTask( 261 FROM_HERE, 262 base::Bind(&ServiceDiscoveryHostClient::ShutdownOnIOThread, this)); 263} 264 265#if defined(OS_POSIX) 266 267void ServiceDiscoveryHostClient::StartOnIOThread() { 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 269 DCHECK(!utility_host_); 270 BrowserThread::PostTaskAndReplyWithResult( 271 BrowserThread::FILE, 272 FROM_HERE, 273 base::Bind(&GetSocketsOnFileThread), 274 base::Bind(&ServiceDiscoveryHostClient::OnSocketsReady, this)); 275} 276 277void ServiceDiscoveryHostClient::OnSocketsReady(const SocketInfoList& sockets) { 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 279 DCHECK(!utility_host_); 280 utility_host_ = UtilityProcessHost::Create( 281 this, base::MessageLoopProxy::current().get())->AsWeakPtr(); 282 if (!utility_host_) 283 return; 284 utility_host_->EnableMDns(); 285 utility_host_->StartBatchMode(); 286 if (sockets.empty()) { 287 ShutdownOnIOThread(); 288 return; 289 } 290 utility_host_->Send(new LocalDiscoveryMsg_SetSockets(sockets)); 291 // Send messages for requests made during network enumeration. 292 for (size_t i = 0; i < delayed_messages_.size(); ++i) 293 utility_host_->Send(delayed_messages_[i]); 294 delayed_messages_.weak_clear(); 295} 296 297#else // OS_POSIX 298 299void ServiceDiscoveryHostClient::StartOnIOThread() { 300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 301 DCHECK(!utility_host_); 302 utility_host_ = UtilityProcessHost::Create( 303 this, base::MessageLoopProxy::current().get())->AsWeakPtr(); 304 if (!utility_host_) 305 return; 306 utility_host_->EnableMDns(); 307 utility_host_->StartBatchMode(); 308 // Windows does not enumerate networks here. 309 DCHECK(delayed_messages_.empty()); 310} 311 312#endif // OS_POSIX 313 314void ServiceDiscoveryHostClient::ShutdownOnIOThread() { 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 316 if (utility_host_) { 317 utility_host_->Send(new LocalDiscoveryMsg_ShutdownLocalDiscovery); 318 utility_host_->EndBatchMode(); 319 utility_host_.reset(); 320 } 321 error_callback_ = base::Closure(); 322} 323 324void ServiceDiscoveryHostClient::Send(IPC::Message* msg) { 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 326 io_runner_->PostTask( 327 FROM_HERE, 328 base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg)); 329} 330 331void ServiceDiscoveryHostClient::SendOnIOThread(IPC::Message* msg) { 332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 333 if (utility_host_) { 334 utility_host_->Send(msg); 335 } else { 336 delayed_messages_.push_back(msg); 337 } 338} 339 340void ServiceDiscoveryHostClient::OnProcessCrashed(int exit_code) { 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 342 DCHECK(!utility_host_); 343 OnError(); 344} 345 346bool ServiceDiscoveryHostClient::OnMessageReceived( 347 const IPC::Message& message) { 348 bool handled = true; 349 IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryHostClient, message) 350 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_Error, OnError) 351 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_WatcherCallback, 352 OnWatcherCallback) 353 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_ResolverCallback, 354 OnResolverCallback) 355 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_LocalDomainResolverCallback, 356 OnLocalDomainResolverCallback) 357 IPC_MESSAGE_UNHANDLED(handled = false) 358 IPC_END_MESSAGE_MAP() 359 return handled; 360} 361 362void ServiceDiscoveryHostClient::InvalidateWatchers() { 363 WatcherCallbacks service_watcher_callbacks; 364 service_watcher_callbacks_.swap(service_watcher_callbacks); 365 service_resolver_callbacks_.clear(); 366 domain_resolver_callbacks_.clear(); 367 368 for (WatcherCallbacks::iterator i = service_watcher_callbacks.begin(); 369 i != service_watcher_callbacks.end(); i++) { 370 if (!i->second.is_null()) { 371 i->second.Run(ServiceWatcher::UPDATE_INVALIDATED, ""); 372 } 373 } 374} 375 376void ServiceDiscoveryHostClient::OnError() { 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 378 if (!error_callback_.is_null()) 379 callback_runner_->PostTask(FROM_HERE, error_callback_); 380} 381 382void ServiceDiscoveryHostClient::OnWatcherCallback( 383 uint64 id, 384 ServiceWatcher::UpdateType update, 385 const std::string& service_name) { 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 387 callback_runner_->PostTask( 388 FROM_HERE, 389 base::Bind(&ServiceDiscoveryHostClient::RunWatcherCallback, this, id, 390 update, service_name)); 391} 392 393void ServiceDiscoveryHostClient::OnResolverCallback( 394 uint64 id, 395 ServiceResolver::RequestStatus status, 396 const ServiceDescription& description) { 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 398 callback_runner_->PostTask( 399 FROM_HERE, 400 base::Bind(&ServiceDiscoveryHostClient::RunResolverCallback, this, id, 401 status, description)); 402} 403 404void ServiceDiscoveryHostClient::OnLocalDomainResolverCallback( 405 uint64 id, 406 bool success, 407 const net::IPAddressNumber& ip_address_ipv4, 408 const net::IPAddressNumber& ip_address_ipv6) { 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 410 callback_runner_->PostTask( 411 FROM_HERE, 412 base::Bind(&ServiceDiscoveryHostClient::RunLocalDomainResolverCallback, 413 this, id, success, ip_address_ipv4, ip_address_ipv6)); 414} 415 416void ServiceDiscoveryHostClient::RunWatcherCallback( 417 uint64 id, 418 ServiceWatcher::UpdateType update, 419 const std::string& service_name) { 420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 421 WatcherCallbacks::iterator it = service_watcher_callbacks_.find(id); 422 if (it != service_watcher_callbacks_.end() && !it->second.is_null()) 423 it->second.Run(update, service_name); 424} 425 426void ServiceDiscoveryHostClient::RunResolverCallback( 427 uint64 id, 428 ServiceResolver::RequestStatus status, 429 const ServiceDescription& description) { 430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 431 ResolverCallbacks::iterator it = service_resolver_callbacks_.find(id); 432 if (it != service_resolver_callbacks_.end() && !it->second.is_null()) 433 it->second.Run(status, description); 434} 435 436void ServiceDiscoveryHostClient::RunLocalDomainResolverCallback( 437 uint64 id, 438 bool success, 439 const net::IPAddressNumber& ip_address_ipv4, 440 const net::IPAddressNumber& ip_address_ipv6) { 441 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 442 DomainResolverCallbacks::iterator it = domain_resolver_callbacks_.find(id); 443 if (it != domain_resolver_callbacks_.end() && !it->second.is_null()) 444 it->second.Run(success, ip_address_ipv4, ip_address_ipv6); 445} 446 447} // namespace local_discovery 448