blob: 29e42c7850699665c01e1e943e4a52e93b58cc49 [file] [log] [blame]
// 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 <map>
#include <string>
#include <vector>
#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);
virtual ~ServiceDiscoveryClientImpl();
// ServiceDiscoveryClient implementation:
virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
virtual scoped_ptr<LocalDomainResolver> 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<ServiceWatcherImpl> {
public:
ServiceWatcherImpl(const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback,
net::MDnsClient* mdns_client);
// Listening will automatically stop when the destructor is called.
virtual ~ServiceWatcherImpl();
// ServiceWatcher implementation:
virtual void Start() OVERRIDE;
virtual void DiscoverNewServices(bool force_update) OVERRIDE;
virtual void SetActivelyRefreshServices(
bool actively_refresh_services) OVERRIDE;
virtual std::string GetServiceType() const OVERRIDE;
virtual void OnRecordUpdate(net::MDnsListener::UpdateType update,
const net::RecordParsed* record) OVERRIDE;
virtual void OnNsecRecord(const std::string& name, unsigned rrtype) OVERRIDE;
virtual void OnCachePurged() OVERRIDE;
virtual void OnTransactionResponse(
scoped_ptr<net::MDnsTransaction>* 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<net::MDnsListener> srv_listener_;
scoped_ptr<net::MDnsListener> txt_listener_;
scoped_ptr<net::MDnsTransaction> srv_transaction_;
std::string service_name_;
net::MDnsClient* mdns_client_;
bool update_pending_;
bool has_ptr_;
bool has_srv_;
};
typedef std::map<std::string, linked_ptr<ServiceListeners> >
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<net::MDnsTransaction>* 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<net::MDnsTransaction> transaction_network_;
scoped_ptr<net::MDnsTransaction> transaction_cache_;
scoped_ptr<net::MDnsListener> 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<ServiceResolverImpl> {
public:
ServiceResolverImpl(const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback,
net::MDnsClient* mdns_client);
virtual ~ServiceResolverImpl();
// ServiceResolver implementation:
virtual void StartResolving() OVERRIDE;
virtual 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<std::string>& 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 has_resolved_;
bool metadata_resolved_;
bool address_resolved_;
scoped_ptr<net::MDnsTransaction> txt_transaction_;
scoped_ptr<net::MDnsTransaction> srv_transaction_;
scoped_ptr<net::MDnsTransaction> 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);
virtual ~LocalDomainResolverImpl();
virtual void Start() OVERRIDE;
const std::string& domain() { return domain_; }
private:
void OnTransactionComplete(
net::MDnsTransaction::Result result,
const net::RecordParsed* record);
scoped_ptr<net::MDnsTransaction> CreateTransaction(uint16 type);
bool IsSuccess();
void SendResolvedAddresses();
std::string domain_;
net::AddressFamily address_family_;
IPAddressCallback callback_;
scoped_ptr<net::MDnsTransaction> transaction_a_;
scoped_ptr<net::MDnsTransaction> transaction_aaaa_;
int transactions_finished_;
net::MDnsClient* mdns_client_;
net::IPAddressNumber address_ipv4_;
net::IPAddressNumber address_ipv6_;
base::CancelableCallback<void()> timeout_callback_;
DISALLOW_COPY_AND_ASSIGN(LocalDomainResolverImpl);
};
} // namespace local_discovery
#endif // CHROME_COMMON_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_