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_
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"
32 class MDnsSocketFactoryImpl
: public MDnsSocketFactory
{
34 MDnsSocketFactoryImpl() {}
35 ~MDnsSocketFactoryImpl() override
{};
37 void CreateSockets(ScopedVector
<DatagramServerSocket
>* sockets
) override
;
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
{
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
);
65 SocketHandler(scoped_ptr
<DatagramServerSocket
> socket
,
66 MDnsConnection
* connection
);
70 void Send(const scoped_refptr
<IOBuffer
>& buffer
, unsigned size
);
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
,
95 void PostOnError(SocketHandler
* loop
, int rv
);
98 // Only socket handlers which successfully bound and started are kept.
99 ScopedVector
<SocketHandler
> socket_handlers_
;
103 base::WeakPtrFactory
<MDnsConnection
> weak_ptr_factory_
;
105 DISALLOW_COPY_AND_ASSIGN(MDnsConnection
);
108 class MDnsListenerImpl
;
110 class NET_EXPORT_PRIVATE MDnsClientImpl
: public MDnsClient
{
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
{
118 Core(base::Clock
* clock
, base::Timer
* timer
);
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
;
141 FRIEND_TEST_ALL_PREFIXES(MDnsTest
, CacheCleanupWithShortTTL
);
143 typedef std::pair
<std::string
, uint16
> ListenerKey
;
144 typedef std::map
<ListenerKey
, base::ObserverList
<MDnsListenerImpl
>*>
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.
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
164 void CleanupObserverList(const ListenerKey
& key
);
166 ListenerMap listeners_
;
171 base::Timer
* cleanup_timer_
;
172 base::Time scheduled_cleanup_
;
174 scoped_ptr
<MDnsConnection
> connection_
;
176 DISALLOW_COPY_AND_ASSIGN(Core
);
180 ~MDnsClientImpl() override
;
182 // MDnsClient implementation:
183 scoped_ptr
<MDnsListener
> CreateListener(
185 const std::string
& name
,
186 MDnsListener::Delegate
* delegate
) override
;
188 scoped_ptr
<MDnsTransaction
> CreateTransaction(
190 const std::string
& name
,
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(); }
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
> {
217 MDnsListenerImpl(uint16 rrtype
,
218 const std::string
& name
,
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();
245 void ScheduleNextRefresh();
251 MDnsClientImpl
* client_
;
252 MDnsListener::Delegate
* delegate_
;
254 base::Time last_update_
;
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
{
267 MDnsTransactionImpl(uint16 rrtype
,
268 const std::string
& name
,
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
;
288 bool is_active() { return !callback_
.is_null(); }
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
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();
313 MDnsTransaction::ResultCallback callback_
;
315 scoped_ptr
<MDnsListener
> listener_
;
316 base::CancelableCallback
<void()> timeout_
;
318 MDnsClientImpl
* client_
;
323 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl
);
327 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_