1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
6#define CHROME_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
7
8#include <map>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/cancelable_callback.h"
14#include "base/memory/linked_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "base/message_loop/message_loop.h"
17#include "chrome/common/local_discovery/service_discovery_client.h"
18#include "net/dns/mdns_client.h"
19
20namespace local_discovery {
21
22class ServiceDiscoveryClientImpl : public ServiceDiscoveryClient {
23 public:
24  // |mdns_client| must outlive the Service Discovery Client.
25  explicit ServiceDiscoveryClientImpl(net::MDnsClient* mdns_client);
26  virtual ~ServiceDiscoveryClientImpl();
27
28  // ServiceDiscoveryClient implementation:
29  virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
30      const std::string& service_type,
31      const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
32
33  virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
34      const std::string& service_name,
35      const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
36
37  virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
38      const std::string& domain,
39      net::AddressFamily address_family,
40      const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
41
42 private:
43  net::MDnsClient* mdns_client_;
44
45  DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientImpl);
46};
47
48class ServiceWatcherImpl : public ServiceWatcher,
49                           public net::MDnsListener::Delegate,
50                           public base::SupportsWeakPtr<ServiceWatcherImpl> {
51 public:
52  ServiceWatcherImpl(const std::string& service_type,
53                     const ServiceWatcher::UpdatedCallback& callback,
54                     net::MDnsClient* mdns_client);
55  // Listening will automatically stop when the destructor is called.
56  virtual ~ServiceWatcherImpl();
57
58  // ServiceWatcher implementation:
59  virtual void Start() OVERRIDE;
60
61  virtual void DiscoverNewServices(bool force_update) OVERRIDE;
62
63  virtual std::string GetServiceType() const OVERRIDE;
64
65  virtual void OnRecordUpdate(net::MDnsListener::UpdateType update,
66                              const net::RecordParsed* record) OVERRIDE;
67
68  virtual void OnNsecRecord(const std::string& name, unsigned rrtype) OVERRIDE;
69
70  virtual void OnCachePurged() OVERRIDE;
71
72  virtual void OnTransactionResponse(
73      scoped_ptr<net::MDnsTransaction>* transaction,
74      net::MDnsTransaction::Result result,
75      const net::RecordParsed* record);
76
77 private:
78  struct ServiceListeners {
79    ServiceListeners(const std::string& service_name,
80                     ServiceWatcherImpl* watcher,
81                     net::MDnsClient* mdns_client);
82    ~ServiceListeners();
83    bool Start();
84
85    void set_update_pending(bool update_pending) {
86      update_pending_ = update_pending;
87    }
88
89    bool update_pending() { return update_pending_; }
90   private:
91    scoped_ptr<net::MDnsListener> srv_listener_;
92    scoped_ptr<net::MDnsListener> txt_listener_;
93    bool update_pending_;
94  };
95
96  typedef std::map<std::string, linked_ptr<ServiceListeners> >
97      ServiceListenersMap;
98
99  void ReadCachedServices();
100  void AddService(const std::string& service);
101  void RemoveService(const std::string& service);
102  bool CreateTransaction(bool active, bool alert_existing_services,
103                         bool force_refresh,
104                         scoped_ptr<net::MDnsTransaction>* transaction);
105
106  void DeferUpdate(ServiceWatcher::UpdateType update_type,
107                   const std::string& service_name);
108  void DeliverDeferredUpdate(ServiceWatcher::UpdateType update_type,
109                             const std::string& service_name);
110
111  std::string service_type_;
112  ServiceListenersMap services_;
113  scoped_ptr<net::MDnsTransaction> transaction_network_;
114  scoped_ptr<net::MDnsTransaction> transaction_cache_;
115  scoped_ptr<net::MDnsListener> listener_;
116
117  ServiceWatcher::UpdatedCallback callback_;
118  bool started_;
119
120  net::MDnsClient* mdns_client_;
121
122  DISALLOW_COPY_AND_ASSIGN(ServiceWatcherImpl);
123};
124
125class ServiceResolverImpl
126    : public ServiceResolver,
127      public base::SupportsWeakPtr<ServiceResolverImpl> {
128 public:
129  ServiceResolverImpl(const std::string& service_name,
130                      const ServiceResolver::ResolveCompleteCallback& callback,
131                      net::MDnsClient* mdns_client);
132
133  virtual ~ServiceResolverImpl();
134
135  // ServiceResolver implementation:
136  virtual void StartResolving() OVERRIDE;
137
138  virtual std::string GetName() const OVERRIDE;
139
140 private:
141  // Respond to transaction finishing for SRV records.
142  void SrvRecordTransactionResponse(net::MDnsTransaction::Result status,
143                                    const net::RecordParsed* record);
144
145  // Respond to transaction finishing for TXT records.
146  void TxtRecordTransactionResponse(net::MDnsTransaction::Result status,
147                                    const net::RecordParsed* record);
148
149  // Respond to transaction finishing for A records.
150  void ARecordTransactionResponse(net::MDnsTransaction::Result status,
151                                  const net::RecordParsed* record);
152
153  void AlertCallbackIfReady();
154
155  void ServiceNotFound(RequestStatus status);
156
157  // Convert a TXT record to a vector of strings (metadata).
158  const std::vector<std::string>& RecordToMetadata(
159      const net::RecordParsed* record) const;
160
161  // Convert an SRV record to a host and port pair.
162  net::HostPortPair RecordToAddress(
163      const net::RecordParsed* record) const;
164
165  // Convert an A record to an IP address.
166  const net::IPAddressNumber& RecordToIPAddress(
167      const net::RecordParsed* record) const;
168
169  // Convert an MDns status to a service discovery status.
170  RequestStatus MDnsStatusToRequestStatus(
171      net::MDnsTransaction::Result status) const;
172
173  bool CreateTxtTransaction();
174  bool CreateSrvTransaction();
175  void CreateATransaction();
176
177  std::string service_name_;
178  ResolveCompleteCallback callback_;
179
180  bool has_resolved_;
181
182  bool metadata_resolved_;
183  bool address_resolved_;
184
185  scoped_ptr<net::MDnsTransaction> txt_transaction_;
186  scoped_ptr<net::MDnsTransaction> srv_transaction_;
187  scoped_ptr<net::MDnsTransaction> a_transaction_;
188
189  ServiceDescription service_staging_;
190
191  net::MDnsClient* mdns_client_;
192
193  DISALLOW_COPY_AND_ASSIGN(ServiceResolverImpl);
194};
195
196class LocalDomainResolverImpl : public LocalDomainResolver {
197 public:
198  LocalDomainResolverImpl(const std::string& domain,
199                          net::AddressFamily address_family,
200                          const IPAddressCallback& callback,
201                          net::MDnsClient* mdns_client);
202  virtual ~LocalDomainResolverImpl();
203
204  virtual void Start() OVERRIDE;
205
206  const std::string& domain() { return domain_; }
207
208 private:
209  void OnTransactionComplete(
210      net::MDnsTransaction::Result result,
211      const net::RecordParsed* record);
212
213  scoped_ptr<net::MDnsTransaction> CreateTransaction(uint16 type);
214
215  std::string domain_;
216  net::AddressFamily address_family_;
217  IPAddressCallback callback_;
218
219  scoped_ptr<net::MDnsTransaction> transaction_a_;
220  scoped_ptr<net::MDnsTransaction> transaction_aaaa_;
221
222  int transaction_failures_;
223
224  net::MDnsClient* mdns_client_;
225
226  DISALLOW_COPY_AND_ASSIGN(LocalDomainResolverImpl);
227};
228
229
230}  // namespace local_discovery
231
232#endif  // CHROME_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
233