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_
13 #include "base/cancelable_callback.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/observer_list.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/ip_endpoint.h"
18 #include "net/dns/mdns_cache.h"
19 #include "net/dns/mdns_client.h"
20 #include "net/udp/datagram_server_socket.h"
21 #include "net/udp/udp_server_socket.h"
22 #include "net/udp/udp_socket.h"
26 class MDnsSocketFactoryImpl
: public MDnsSocketFactory
{
28 MDnsSocketFactoryImpl() {};
29 ~MDnsSocketFactoryImpl() override
{};
31 void CreateSockets(ScopedVector
<DatagramServerSocket
>* sockets
) override
;
34 DISALLOW_COPY_AND_ASSIGN(MDnsSocketFactoryImpl
);
37 // A connection to the network for multicast DNS clients. It reads data into
38 // DnsResponse objects and alerts the delegate that a packet has been received.
39 class NET_EXPORT_PRIVATE MDnsConnection
{
43 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|.
44 virtual void HandlePacket(DnsResponse
* response
, int bytes_read
) = 0;
45 virtual void OnConnectionError(int error
) = 0;
46 virtual ~Delegate() {}
49 explicit MDnsConnection(MDnsConnection::Delegate
* delegate
);
50 virtual ~MDnsConnection();
52 // Both methods return true if at least one of the socket handlers succeeded.
53 bool Init(MDnsSocketFactory
* socket_factory
);
54 void Send(const scoped_refptr
<IOBuffer
>& buffer
, unsigned size
);
59 SocketHandler(scoped_ptr
<DatagramServerSocket
> socket
,
60 MDnsConnection
* connection
);
64 void Send(const scoped_refptr
<IOBuffer
>& buffer
, unsigned size
);
68 void OnDatagramReceived(int rv
);
70 // Callback for when sending a query has finished.
71 void SendDone(int rv
);
73 scoped_ptr
<DatagramServerSocket
> socket_
;
74 MDnsConnection
* connection_
;
75 IPEndPoint recv_addr_
;
76 DnsResponse response_
;
77 IPEndPoint multicast_addr_
;
78 bool send_in_progress_
;
79 std::queue
<std::pair
<scoped_refptr
<IOBuffer
>, unsigned> > send_queue_
;
81 DISALLOW_COPY_AND_ASSIGN(SocketHandler
);
84 // Callback for handling a datagram being received on either ipv4 or ipv6.
85 void OnDatagramReceived(DnsResponse
* response
,
86 const IPEndPoint
& recv_addr
,
89 void PostOnError(SocketHandler
* loop
, int rv
);
92 // Only socket handlers which successfully bound and started are kept.
93 ScopedVector
<SocketHandler
> socket_handlers_
;
97 base::WeakPtrFactory
<MDnsConnection
> weak_ptr_factory_
;
99 DISALLOW_COPY_AND_ASSIGN(MDnsConnection
);
102 class MDnsListenerImpl
;
104 class NET_EXPORT_PRIVATE MDnsClientImpl
: public MDnsClient
{
106 // The core object exists while the MDnsClient is listening, and is deleted
107 // whenever the number of listeners reaches zero. The deletion happens
108 // asychronously, so destroying the last listener does not immediately
109 // invalidate the core.
110 class Core
: public base::SupportsWeakPtr
<Core
>, MDnsConnection::Delegate
{
115 // Initialize the core. Returns true on success.
116 bool Init(MDnsSocketFactory
* socket_factory
);
118 // Send a query with a specific rrtype and name. Returns true on success.
119 bool SendQuery(uint16 rrtype
, std::string name
);
121 // Add/remove a listener to the list of listeners.
122 void AddListener(MDnsListenerImpl
* listener
);
123 void RemoveListener(MDnsListenerImpl
* listener
);
125 // Query the cache for records of a specific type and name.
126 void QueryCache(uint16 rrtype
, const std::string
& name
,
127 std::vector
<const RecordParsed
*>* records
) const;
129 // Parse the response and alert relevant listeners.
130 void HandlePacket(DnsResponse
* response
, int bytes_read
) override
;
132 void OnConnectionError(int error
) override
;
135 typedef std::pair
<std::string
, uint16
> ListenerKey
;
136 typedef std::map
<ListenerKey
, ObserverList
<MDnsListenerImpl
>* >
139 // Alert listeners of an update to the cache.
140 void AlertListeners(MDnsCache::UpdateType update_type
,
141 const ListenerKey
& key
, const RecordParsed
* record
);
143 // Schedule a cache cleanup to a specific time, cancelling other cleanups.
144 void ScheduleCleanup(base::Time cleanup
);
146 // Clean up the cache and schedule a new cleanup.
149 // Callback for when a record is removed from the cache.
150 void OnRecordRemoved(const RecordParsed
* record
);
152 void NotifyNsecRecord(const RecordParsed
* record
);
154 // Delete and erase the observer list for |key|. Only deletes the observer
156 void CleanupObserverList(const ListenerKey
& key
);
158 ListenerMap listeners_
;
162 base::CancelableClosure cleanup_callback_
;
163 base::Time scheduled_cleanup_
;
165 scoped_ptr
<MDnsConnection
> connection_
;
167 DISALLOW_COPY_AND_ASSIGN(Core
);
171 ~MDnsClientImpl() override
;
173 // MDnsClient implementation:
174 scoped_ptr
<MDnsListener
> CreateListener(
176 const std::string
& name
,
177 MDnsListener::Delegate
* delegate
) override
;
179 scoped_ptr
<MDnsTransaction
> CreateTransaction(
181 const std::string
& name
,
183 const MDnsTransaction::ResultCallback
& callback
) override
;
185 bool StartListening(MDnsSocketFactory
* socket_factory
) override
;
186 void StopListening() override
;
187 bool IsListening() const override
;
189 Core
* core() { return core_
.get(); }
192 scoped_ptr
<Core
> core_
;
194 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl
);
197 class MDnsListenerImpl
: public MDnsListener
,
198 public base::SupportsWeakPtr
<MDnsListenerImpl
> {
200 MDnsListenerImpl(uint16 rrtype
,
201 const std::string
& name
,
202 MDnsListener::Delegate
* delegate
,
203 MDnsClientImpl
* client
);
205 ~MDnsListenerImpl() override
;
207 // MDnsListener implementation:
208 bool Start() override
;
210 // Actively refresh any received records.
211 void SetActiveRefresh(bool active_refresh
) override
;
213 const std::string
& GetName() const override
;
215 uint16
GetType() const override
;
217 MDnsListener::Delegate
* delegate() { return delegate_
; }
219 // Alert the delegate of a record update.
220 void HandleRecordUpdate(MDnsCache::UpdateType update_type
,
221 const RecordParsed
* record_parsed
);
223 // Alert the delegate of the existence of an Nsec record.
224 void AlertNsecRecord();
227 void ScheduleNextRefresh();
232 MDnsClientImpl
* client_
;
233 MDnsListener::Delegate
* delegate_
;
235 base::Time last_update_
;
238 bool active_refresh_
;
240 base::CancelableClosure next_refresh_
;
241 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl
);
244 class MDnsTransactionImpl
: public base::SupportsWeakPtr
<MDnsTransactionImpl
>,
245 public MDnsTransaction
,
246 public MDnsListener::Delegate
{
248 MDnsTransactionImpl(uint16 rrtype
,
249 const std::string
& name
,
251 const MDnsTransaction::ResultCallback
& callback
,
252 MDnsClientImpl
* client
);
253 ~MDnsTransactionImpl() override
;
255 // MDnsTransaction implementation:
256 bool Start() override
;
258 const std::string
& GetName() const override
;
259 uint16
GetType() const override
;
261 // MDnsListener::Delegate implementation:
262 void OnRecordUpdate(MDnsListener::UpdateType update
,
263 const RecordParsed
* record
) override
;
264 void OnNsecRecord(const std::string
& name
, unsigned type
) override
;
266 void OnCachePurged() override
;
269 bool is_active() { return !callback_
.is_null(); }
273 // Trigger the callback and reset all related variables.
274 void TriggerCallback(MDnsTransaction::Result result
,
275 const RecordParsed
* record
);
277 // Internal callback for when a cache record is found.
278 void CacheRecordFound(const RecordParsed
* record
);
280 // Signal the transactionis over and release all related resources.
281 void SignalTransactionOver();
283 // Reads records from the cache and calls the callback for every
285 void ServeRecordsFromCache();
287 // Send a query to the network and set up a timeout to time out the
288 // transaction. Returns false if it fails to start listening on the network
289 // or if it fails to send a query.
290 bool QueryAndListen();
294 MDnsTransaction::ResultCallback callback_
;
296 scoped_ptr
<MDnsListener
> listener_
;
297 base::CancelableCallback
<void()> timeout_
;
299 MDnsClientImpl
* client_
;
304 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl
);
308 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_