root/chrome/utility/local_discovery/service_discovery_client_impl.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright 2013 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_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
#define CHROME_UTILITY_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_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_

/* [<][>][^][v][top][bottom][index][help] */