// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_COMMON_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_ #define CHROME_COMMON_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_ #include #include #include #include "base/callback.h" #include "base/cancelable_callback.h" #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "chrome/common/local_discovery/service_discovery_client.h" #include "net/dns/mdns_client.h" namespace local_discovery { class ServiceDiscoveryClientImpl : public ServiceDiscoveryClient { public: // |mdns_client| must outlive the Service Discovery Client. explicit ServiceDiscoveryClientImpl(net::MDnsClient* mdns_client); ~ServiceDiscoveryClientImpl() override; // ServiceDiscoveryClient implementation: scoped_ptr CreateServiceWatcher( const std::string& service_type, const ServiceWatcher::UpdatedCallback& callback) override; scoped_ptr CreateServiceResolver( const std::string& service_name, const ServiceResolver::ResolveCompleteCallback& callback) override; scoped_ptr CreateLocalDomainResolver( const std::string& domain, net::AddressFamily address_family, const LocalDomainResolver::IPAddressCallback& callback) override; private: net::MDnsClient* mdns_client_; DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientImpl); }; class ServiceWatcherImpl : public ServiceWatcher, public net::MDnsListener::Delegate, public base::SupportsWeakPtr { public: ServiceWatcherImpl(const std::string& service_type, const ServiceWatcher::UpdatedCallback& callback, net::MDnsClient* mdns_client); // Listening will automatically stop when the destructor is called. ~ServiceWatcherImpl() override; // ServiceWatcher implementation: void Start() override; void DiscoverNewServices(bool force_update) override; void SetActivelyRefreshServices(bool actively_refresh_services) override; std::string GetServiceType() const override; void OnRecordUpdate(net::MDnsListener::UpdateType update, const net::RecordParsed* record) override; void OnNsecRecord(const std::string& name, unsigned rrtype) override; void OnCachePurged() override; virtual void OnTransactionResponse( scoped_ptr* transaction, net::MDnsTransaction::Result result, const net::RecordParsed* record); private: struct ServiceListeners { ServiceListeners(const std::string& service_name, ServiceWatcherImpl* watcher, net::MDnsClient* mdns_client); ~ServiceListeners(); bool Start(); void SetActiveRefresh(bool auto_update); void set_update_pending(bool update_pending) { update_pending_ = update_pending; } bool update_pending() { return update_pending_; } void set_has_ptr(bool has_ptr) { has_ptr_ = has_ptr; } void set_has_srv(bool has_srv); bool has_ptr_or_srv() { return has_ptr_ || has_srv_; } private: void OnSRVRecord(net::MDnsTransaction::Result result, const net::RecordParsed* record); void DoQuerySRV(); scoped_ptr srv_listener_; scoped_ptr txt_listener_; scoped_ptr srv_transaction_; std::string service_name_; net::MDnsClient* mdns_client_; bool update_pending_; bool has_ptr_; bool has_srv_; }; typedef std::map > ServiceListenersMap; void ReadCachedServices(); void AddService(const std::string& service); void RemovePTR(const std::string& service); void RemoveSRV(const std::string& service); void AddSRV(const std::string& service); bool CreateTransaction(bool active, bool alert_existing_services, bool force_refresh, scoped_ptr* transaction); void DeferUpdate(ServiceWatcher::UpdateType update_type, const std::string& service_name); void DeliverDeferredUpdate(ServiceWatcher::UpdateType update_type, const std::string& service_name); void ScheduleQuery(int timeout_seconds); void SendQuery(int next_timeout_seconds, bool force_update); std::string service_type_; ServiceListenersMap services_; scoped_ptr transaction_network_; scoped_ptr transaction_cache_; scoped_ptr listener_; ServiceWatcher::UpdatedCallback callback_; bool started_; bool actively_refresh_services_; net::MDnsClient* mdns_client_; DISALLOW_COPY_AND_ASSIGN(ServiceWatcherImpl); }; class ServiceResolverImpl : public ServiceResolver, public base::SupportsWeakPtr { public: ServiceResolverImpl(const std::string& service_name, const ServiceResolver::ResolveCompleteCallback& callback, net::MDnsClient* mdns_client); ~ServiceResolverImpl() override; // ServiceResolver implementation: void StartResolving() override; std::string GetName() const override; private: // Respond to transaction finishing for SRV records. void SrvRecordTransactionResponse(net::MDnsTransaction::Result status, const net::RecordParsed* record); // Respond to transaction finishing for TXT records. void TxtRecordTransactionResponse(net::MDnsTransaction::Result status, const net::RecordParsed* record); // Respond to transaction finishing for A records. void ARecordTransactionResponse(net::MDnsTransaction::Result status, const net::RecordParsed* record); void AlertCallbackIfReady(); void ServiceNotFound(RequestStatus status); // Convert a TXT record to a vector of strings (metadata). const std::vector& RecordToMetadata( const net::RecordParsed* record) const; // Convert an SRV record to a host and port pair. net::HostPortPair RecordToAddress( const net::RecordParsed* record) const; // Convert an A record to an IP address. const net::IPAddressNumber& RecordToIPAddress( const net::RecordParsed* record) const; // Convert an MDns status to a service discovery status. RequestStatus MDnsStatusToRequestStatus( net::MDnsTransaction::Result status) const; bool CreateTxtTransaction(); bool CreateSrvTransaction(); void CreateATransaction(); std::string service_name_; ResolveCompleteCallback callback_; bool metadata_resolved_; bool address_resolved_; scoped_ptr txt_transaction_; scoped_ptr srv_transaction_; scoped_ptr a_transaction_; ServiceDescription service_staging_; net::MDnsClient* mdns_client_; DISALLOW_COPY_AND_ASSIGN(ServiceResolverImpl); }; class LocalDomainResolverImpl : public LocalDomainResolver { public: LocalDomainResolverImpl(const std::string& domain, net::AddressFamily address_family, const IPAddressCallback& callback, net::MDnsClient* mdns_client); ~LocalDomainResolverImpl() override; void Start() override; const std::string& domain() { return domain_; } private: void OnTransactionComplete( net::MDnsTransaction::Result result, const net::RecordParsed* record); scoped_ptr CreateTransaction(uint16 type); bool IsSuccess(); void SendResolvedAddresses(); std::string domain_; net::AddressFamily address_family_; IPAddressCallback callback_; scoped_ptr transaction_a_; scoped_ptr transaction_aaaa_; int transactions_finished_; net::MDnsClient* mdns_client_; net::IPAddressNumber address_ipv4_; net::IPAddressNumber address_ipv6_; base::CancelableCallback timeout_callback_; DISALLOW_COPY_AND_ASSIGN(LocalDomainResolverImpl); }; } // namespace local_discovery #endif // CHROME_COMMON_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_