Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / dns / mdns_client_impl.h
blobe788601fd76ec4e608aab43d523370e5f5be8a62
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.
5 #ifndef NET_DNS_MDNS_CLIENT_IMPL_H_
6 #define NET_DNS_MDNS_CLIENT_IMPL_H_
8 #include <map>
9 #include <queue>
10 #include <string>
11 #include <utility>
12 #include <vector>
14 #include "base/cancelable_callback.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/observer_list.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h"
19 #include "net/dns/mdns_cache.h"
20 #include "net/dns/mdns_client.h"
21 #include "net/udp/datagram_server_socket.h"
22 #include "net/udp/udp_server_socket.h"
23 #include "net/udp/udp_socket.h"
25 namespace base {
26 class Clock;
27 class Timer;
28 } // namespace base
30 namespace net {
32 class MDnsSocketFactoryImpl : public MDnsSocketFactory {
33 public:
34 MDnsSocketFactoryImpl() {}
35 ~MDnsSocketFactoryImpl() override{};
37 void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) override;
39 private:
40 DISALLOW_COPY_AND_ASSIGN(MDnsSocketFactoryImpl);
43 // A connection to the network for multicast DNS clients. It reads data into
44 // DnsResponse objects and alerts the delegate that a packet has been received.
45 class NET_EXPORT_PRIVATE MDnsConnection {
46 public:
47 class Delegate {
48 public:
49 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|.
50 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0;
51 virtual void OnConnectionError(int error) = 0;
52 virtual ~Delegate() {}
55 explicit MDnsConnection(MDnsConnection::Delegate* delegate);
56 virtual ~MDnsConnection();
58 // Both methods return true if at least one of the socket handlers succeeded.
59 bool Init(MDnsSocketFactory* socket_factory);
60 void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
62 private:
63 class SocketHandler {
64 public:
65 SocketHandler(scoped_ptr<DatagramServerSocket> socket,
66 MDnsConnection* connection);
67 ~SocketHandler();
69 int Start();
70 void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
72 private:
73 int DoLoop(int rv);
74 void OnDatagramReceived(int rv);
76 // Callback for when sending a query has finished.
77 void SendDone(int rv);
79 scoped_ptr<DatagramServerSocket> socket_;
80 MDnsConnection* connection_;
81 IPEndPoint recv_addr_;
82 DnsResponse response_;
83 IPEndPoint multicast_addr_;
84 bool send_in_progress_;
85 std::queue<std::pair<scoped_refptr<IOBuffer>, unsigned> > send_queue_;
87 DISALLOW_COPY_AND_ASSIGN(SocketHandler);
90 // Callback for handling a datagram being received on either ipv4 or ipv6.
91 void OnDatagramReceived(DnsResponse* response,
92 const IPEndPoint& recv_addr,
93 int bytes_read);
95 void PostOnError(SocketHandler* loop, int rv);
96 void OnError(int rv);
98 // Only socket handlers which successfully bound and started are kept.
99 ScopedVector<SocketHandler> socket_handlers_;
101 Delegate* delegate_;
103 base::WeakPtrFactory<MDnsConnection> weak_ptr_factory_;
105 DISALLOW_COPY_AND_ASSIGN(MDnsConnection);
108 class MDnsListenerImpl;
110 class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
111 public:
112 // The core object exists while the MDnsClient is listening, and is deleted
113 // whenever the number of listeners reaches zero. The deletion happens
114 // asychronously, so destroying the last listener does not immediately
115 // invalidate the core.
116 class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate {
117 public:
118 Core(base::Clock* clock, base::Timer* timer);
119 ~Core() override;
121 // Initialize the core. Returns true on success.
122 bool Init(MDnsSocketFactory* socket_factory);
124 // Send a query with a specific rrtype and name. Returns true on success.
125 bool SendQuery(uint16 rrtype, std::string name);
127 // Add/remove a listener to the list of listeners.
128 void AddListener(MDnsListenerImpl* listener);
129 void RemoveListener(MDnsListenerImpl* listener);
131 // Query the cache for records of a specific type and name.
132 void QueryCache(uint16 rrtype, const std::string& name,
133 std::vector<const RecordParsed*>* records) const;
135 // Parse the response and alert relevant listeners.
136 void HandlePacket(DnsResponse* response, int bytes_read) override;
138 void OnConnectionError(int error) override;
140 private:
141 FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
143 typedef std::pair<std::string, uint16> ListenerKey;
144 typedef std::map<ListenerKey, base::ObserverList<MDnsListenerImpl>*>
145 ListenerMap;
147 // Alert listeners of an update to the cache.
148 void AlertListeners(MDnsCache::UpdateType update_type,
149 const ListenerKey& key, const RecordParsed* record);
151 // Schedule a cache cleanup to a specific time, cancelling other cleanups.
152 void ScheduleCleanup(base::Time cleanup);
154 // Clean up the cache and schedule a new cleanup.
155 void DoCleanup();
157 // Callback for when a record is removed from the cache.
158 void OnRecordRemoved(const RecordParsed* record);
160 void NotifyNsecRecord(const RecordParsed* record);
162 // Delete and erase the observer list for |key|. Only deletes the observer
163 // list if is empty.
164 void CleanupObserverList(const ListenerKey& key);
166 ListenerMap listeners_;
168 MDnsCache cache_;
170 base::Clock* clock_;
171 base::Timer* cleanup_timer_;
172 base::Time scheduled_cleanup_;
174 scoped_ptr<MDnsConnection> connection_;
176 DISALLOW_COPY_AND_ASSIGN(Core);
179 MDnsClientImpl();
180 ~MDnsClientImpl() override;
182 // MDnsClient implementation:
183 scoped_ptr<MDnsListener> CreateListener(
184 uint16 rrtype,
185 const std::string& name,
186 MDnsListener::Delegate* delegate) override;
188 scoped_ptr<MDnsTransaction> CreateTransaction(
189 uint16 rrtype,
190 const std::string& name,
191 int flags,
192 const MDnsTransaction::ResultCallback& callback) override;
194 bool StartListening(MDnsSocketFactory* socket_factory) override;
195 void StopListening() override;
196 bool IsListening() const override;
198 Core* core() { return core_.get(); }
200 private:
201 FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
203 // Test constructor, takes a mock clock and mock timer.
204 MDnsClientImpl(scoped_ptr<base::Clock> clock,
205 scoped_ptr<base::Timer> cleanup_timer);
207 scoped_ptr<Core> core_;
208 scoped_ptr<base::Clock> clock_;
209 scoped_ptr<base::Timer> cleanup_timer_;
211 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl);
214 class MDnsListenerImpl : public MDnsListener,
215 public base::SupportsWeakPtr<MDnsListenerImpl> {
216 public:
217 MDnsListenerImpl(uint16 rrtype,
218 const std::string& name,
219 base::Clock* clock,
220 MDnsListener::Delegate* delegate,
221 MDnsClientImpl* client);
223 ~MDnsListenerImpl() override;
225 // MDnsListener implementation:
226 bool Start() override;
228 // Actively refresh any received records.
229 void SetActiveRefresh(bool active_refresh) override;
231 const std::string& GetName() const override;
233 uint16 GetType() const override;
235 MDnsListener::Delegate* delegate() { return delegate_; }
237 // Alert the delegate of a record update.
238 void HandleRecordUpdate(MDnsCache::UpdateType update_type,
239 const RecordParsed* record_parsed);
241 // Alert the delegate of the existence of an Nsec record.
242 void AlertNsecRecord();
244 private:
245 void ScheduleNextRefresh();
246 void DoRefresh();
248 uint16 rrtype_;
249 std::string name_;
250 base::Clock* clock_;
251 MDnsClientImpl* client_;
252 MDnsListener::Delegate* delegate_;
254 base::Time last_update_;
255 uint32 ttl_;
256 bool started_;
257 bool active_refresh_;
259 base::CancelableClosure next_refresh_;
260 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl);
263 class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>,
264 public MDnsTransaction,
265 public MDnsListener::Delegate {
266 public:
267 MDnsTransactionImpl(uint16 rrtype,
268 const std::string& name,
269 int flags,
270 const MDnsTransaction::ResultCallback& callback,
271 MDnsClientImpl* client);
272 ~MDnsTransactionImpl() override;
274 // MDnsTransaction implementation:
275 bool Start() override;
277 const std::string& GetName() const override;
278 uint16 GetType() const override;
280 // MDnsListener::Delegate implementation:
281 void OnRecordUpdate(MDnsListener::UpdateType update,
282 const RecordParsed* record) override;
283 void OnNsecRecord(const std::string& name, unsigned type) override;
285 void OnCachePurged() override;
287 private:
288 bool is_active() { return !callback_.is_null(); }
290 void Reset();
292 // Trigger the callback and reset all related variables.
293 void TriggerCallback(MDnsTransaction::Result result,
294 const RecordParsed* record);
296 // Internal callback for when a cache record is found.
297 void CacheRecordFound(const RecordParsed* record);
299 // Signal the transactionis over and release all related resources.
300 void SignalTransactionOver();
302 // Reads records from the cache and calls the callback for every
303 // record read.
304 void ServeRecordsFromCache();
306 // Send a query to the network and set up a timeout to time out the
307 // transaction. Returns false if it fails to start listening on the network
308 // or if it fails to send a query.
309 bool QueryAndListen();
311 uint16 rrtype_;
312 std::string name_;
313 MDnsTransaction::ResultCallback callback_;
315 scoped_ptr<MDnsListener> listener_;
316 base::CancelableCallback<void()> timeout_;
318 MDnsClientImpl* client_;
320 bool started_;
321 int flags_;
323 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl);
326 } // namespace net
327 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_