blob: 181a220c9518eea684999d6de412897687c6a38a [file] [log] [blame]
[email protected]245b164e2013-06-13 22:31:421// 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 NET_DNS_MDNS_CLIENT_IMPL_H_
6#define NET_DNS_MDNS_CLIENT_IMPL_H_
7
Avi Drissman13fc8932015-12-20 04:40:468#include <stdint.h>
9
[email protected]245b164e2013-06-13 22:31:4210#include <map>
danakj22f90e72016-04-16 01:55:4011#include <memory>
[email protected]245b164e2013-06-13 22:31:4212#include <string>
13#include <utility>
14#include <vector>
15
16#include "base/cancelable_callback.h"
Brett Wilsonc6a0c822017-09-12 00:04:2917#include "base/containers/queue.h"
thestiga0e18cd2015-09-25 04:58:3618#include "base/gtest_prod_util.h"
Avi Drissman13fc8932015-12-20 04:40:4619#include "base/macros.h"
[email protected]245b164e2013-06-13 22:31:4220#include "base/observer_list.h"
21#include "net/base/io_buffer.h"
22#include "net/base/ip_endpoint.h"
bnc81c46c1f2016-10-04 16:25:5923#include "net/base/net_export.h"
[email protected]245b164e2013-06-13 22:31:4224#include "net/dns/mdns_cache.h"
25#include "net/dns/mdns_client.h"
tfarina5dd13c22016-11-16 12:08:2626#include "net/socket/datagram_server_socket.h"
27#include "net/socket/udp_server_socket.h"
28#include "net/socket/udp_socket.h"
[email protected]245b164e2013-06-13 22:31:4229
kmarshall3e740be2015-03-02 21:30:4430namespace base {
31class Clock;
tzik08d8d6e2018-07-09 04:11:4732class OneShotTimer;
kmarshall3e740be2015-03-02 21:30:4433} // namespace base
34
[email protected]245b164e2013-06-13 22:31:4235namespace net {
36
Eric Orth9871aafa2018-10-02 19:59:1837class NetLog;
38
[email protected]95b331b42013-12-02 06:26:3139class MDnsSocketFactoryImpl : public MDnsSocketFactory {
40 public:
Eric Orth9871aafa2018-10-02 19:59:1841 MDnsSocketFactoryImpl() : net_log_(nullptr) {}
42 explicit MDnsSocketFactoryImpl(NetLog* net_log) : net_log_(net_log) {}
Peter Boström293b1342021-09-22 17:31:4343
44 MDnsSocketFactoryImpl(const MDnsSocketFactoryImpl&) = delete;
45 MDnsSocketFactoryImpl& operator=(const MDnsSocketFactoryImpl&) = delete;
46
juncai1ee189bd2017-06-09 04:25:4347 ~MDnsSocketFactoryImpl() override {}
[email protected]95b331b42013-12-02 06:26:3148
Qingsi Wang5410ef0b2019-03-05 20:26:4749 void CreateSockets(
50 std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override;
[email protected]95b331b42013-12-02 06:26:3151
52 private:
Eric Orth9871aafa2018-10-02 19:59:1853 NetLog* const net_log_;
[email protected]95b331b42013-12-02 06:26:3154};
55
[email protected]245b164e2013-06-13 22:31:4256// A connection to the network for multicast DNS clients. It reads data into
57// DnsResponse objects and alerts the delegate that a packet has been received.
[email protected]ba77c27f2013-07-02 22:34:3258class NET_EXPORT_PRIVATE MDnsConnection {
[email protected]245b164e2013-06-13 22:31:4259 public:
[email protected]245b164e2013-06-13 22:31:4260 class Delegate {
61 public:
62 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|.
63 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0;
64 virtual void OnConnectionError(int error) = 0;
65 virtual ~Delegate() {}
66 };
67
[email protected]e4411fbe2013-09-26 21:10:1168 explicit MDnsConnection(MDnsConnection::Delegate* delegate);
Peter Boström293b1342021-09-22 17:31:4369
70 MDnsConnection(const MDnsConnection&) = delete;
71 MDnsConnection& operator=(const MDnsConnection&) = delete;
72
[email protected]245b164e2013-06-13 22:31:4273 virtual ~MDnsConnection();
74
Eric Orthe857ebb2019-03-13 23:02:0775 // Succeeds if at least one of the socket handlers succeeded.
76 int Init(MDnsSocketFactory* socket_factory);
vitalybuka20859742014-09-22 23:42:3077 void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
[email protected]245b164e2013-06-13 22:31:4278
79 private:
80 class SocketHandler {
81 public:
Qingsi Wang5410ef0b2019-03-05 20:26:4782 SocketHandler(std::unique_ptr<DatagramServerSocket> socket,
[email protected]95b331b42013-12-02 06:26:3183 MDnsConnection* connection);
Peter Boström293b1342021-09-22 17:31:4384
85 SocketHandler(const SocketHandler&) = delete;
86 SocketHandler& operator=(const SocketHandler&) = delete;
87
[email protected]245b164e2013-06-13 22:31:4288 ~SocketHandler();
[email protected]245b164e2013-06-13 22:31:4289
[email protected]95b331b42013-12-02 06:26:3190 int Start();
vitalybuka20859742014-09-22 23:42:3091 void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
[email protected]245b164e2013-06-13 22:31:4292
93 private:
[email protected]03dd94252013-09-01 23:25:3194 int DoLoop(int rv);
[email protected]245b164e2013-06-13 22:31:4295 void OnDatagramReceived(int rv);
96
97 // Callback for when sending a query has finished.
98 void SendDone(int rv);
99
Qingsi Wang5410ef0b2019-03-05 20:26:47100 std::unique_ptr<DatagramServerSocket> socket_;
[email protected]245b164e2013-06-13 22:31:42101 MDnsConnection* connection_;
102 IPEndPoint recv_addr_;
[email protected]95b331b42013-12-02 06:26:31103 DnsResponse response_;
[email protected]245b164e2013-06-13 22:31:42104 IPEndPoint multicast_addr_;
vitalybuka20859742014-09-22 23:42:30105 bool send_in_progress_;
Brett Wilsonc6a0c822017-09-12 00:04:29106 base::queue<std::pair<scoped_refptr<IOBuffer>, unsigned>> send_queue_;
[email protected]245b164e2013-06-13 22:31:42107 };
108
109 // Callback for handling a datagram being received on either ipv4 or ipv6.
110 void OnDatagramReceived(DnsResponse* response,
111 const IPEndPoint& recv_addr,
112 int bytes_read);
113
vitalybuka20859742014-09-22 23:42:30114 void PostOnError(SocketHandler* loop, int rv);
115 void OnError(int rv);
[email protected]245b164e2013-06-13 22:31:42116
[email protected]e4411fbe2013-09-26 21:10:11117 // Only socket handlers which successfully bound and started are kept.
danakj22f90e72016-04-16 01:55:40118 std::vector<std::unique_ptr<SocketHandler>> socket_handlers_;
[email protected]245b164e2013-06-13 22:31:42119
120 Delegate* delegate_;
121
Jeremy Romand54000b22019-07-08 18:40:16122 base::WeakPtrFactory<MDnsConnection> weak_ptr_factory_{this};
[email protected]245b164e2013-06-13 22:31:42123};
124
125class MDnsListenerImpl;
126
[email protected]ba77c27f2013-07-02 22:34:32127class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
[email protected]245b164e2013-06-13 22:31:42128 public:
[email protected]21df16962013-07-01 17:39:53129 // The core object exists while the MDnsClient is listening, and is deleted
130 // whenever the number of listeners reaches zero. The deletion happens
131 // asychronously, so destroying the last listener does not immediately
132 // invalidate the core.
[email protected]245b164e2013-06-13 22:31:42133 class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate {
134 public:
tzik08d8d6e2018-07-09 04:11:47135 Core(base::Clock* clock, base::OneShotTimer* timer);
Peter Boström293b1342021-09-22 17:31:43136
137 Core(const Core&) = delete;
138 Core& operator=(const Core&) = delete;
139
dcheng67be2b1f2014-10-27 21:47:29140 ~Core() override;
[email protected]245b164e2013-06-13 22:31:42141
Eric Orthe857ebb2019-03-13 23:02:07142 // Initialize the core.
143 int Init(MDnsSocketFactory* socket_factory);
[email protected]245b164e2013-06-13 22:31:42144
145 // Send a query with a specific rrtype and name. Returns true on success.
Avi Drissman13fc8932015-12-20 04:40:46146 bool SendQuery(uint16_t rrtype, const std::string& name);
[email protected]245b164e2013-06-13 22:31:42147
[email protected]21df16962013-07-01 17:39:53148 // Add/remove a listener to the list of listeners.
[email protected]245b164e2013-06-13 22:31:42149 void AddListener(MDnsListenerImpl* listener);
150 void RemoveListener(MDnsListenerImpl* listener);
151
152 // Query the cache for records of a specific type and name.
Avi Drissman13fc8932015-12-20 04:40:46153 void QueryCache(uint16_t rrtype,
154 const std::string& name,
[email protected]245b164e2013-06-13 22:31:42155 std::vector<const RecordParsed*>* records) const;
156
157 // Parse the response and alert relevant listeners.
dcheng67be2b1f2014-10-27 21:47:29158 void HandlePacket(DnsResponse* response, int bytes_read) override;
[email protected]245b164e2013-06-13 22:31:42159
dcheng67be2b1f2014-10-27 21:47:29160 void OnConnectionError(int error) override;
[email protected]245b164e2013-06-13 22:31:42161
Eric Orthacdd8ae2019-03-29 22:07:19162 MDnsCache* cache_for_testing() { return &cache_; }
163
[email protected]245b164e2013-06-13 22:31:42164 private:
kmarshall3e740be2015-03-02 21:30:44165 FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
166
Piotr Pawliczek3318cc92020-07-25 05:10:13167 class ListenerKey {
168 public:
169 ListenerKey(const std::string& name, uint16_t type);
170 ListenerKey(const ListenerKey&) = default;
171 ListenerKey(ListenerKey&&) = default;
172 bool operator<(const ListenerKey& key) const;
173 const std::string& name_lowercase() const { return name_lowercase_; }
174 uint16_t type() const { return type_; }
175
176 private:
177 std::string name_lowercase_;
178 uint16_t type_;
179 };
Trent Apteda250ec3ab2018-08-19 08:52:19180 typedef base::ObserverList<MDnsListenerImpl>::Unchecked ObserverListType;
181 typedef std::map<ListenerKey, std::unique_ptr<ObserverListType>>
brettw236d3172015-06-03 16:31:43182 ListenerMap;
[email protected]245b164e2013-06-13 22:31:42183
184 // Alert listeners of an update to the cache.
[email protected]bdd6c3d2014-01-30 08:07:42185 void AlertListeners(MDnsCache::UpdateType update_type,
[email protected]245b164e2013-06-13 22:31:42186 const ListenerKey& key, const RecordParsed* record);
187
188 // Schedule a cache cleanup to a specific time, cancelling other cleanups.
189 void ScheduleCleanup(base::Time cleanup);
190
191 // Clean up the cache and schedule a new cleanup.
192 void DoCleanup();
193
194 // Callback for when a record is removed from the cache.
195 void OnRecordRemoved(const RecordParsed* record);
196
[email protected]21df16962013-07-01 17:39:53197 void NotifyNsecRecord(const RecordParsed* record);
198
199 // Delete and erase the observer list for |key|. Only deletes the observer
200 // list if is empty.
201 void CleanupObserverList(const ListenerKey& key);
202
[email protected]245b164e2013-06-13 22:31:42203 ListenerMap listeners_;
204
[email protected]245b164e2013-06-13 22:31:42205 MDnsCache cache_;
206
kmarshall3e740be2015-03-02 21:30:44207 base::Clock* clock_;
tzik08d8d6e2018-07-09 04:11:47208 base::OneShotTimer* cleanup_timer_;
[email protected]245b164e2013-06-13 22:31:42209 base::Time scheduled_cleanup_;
210
danakj22f90e72016-04-16 01:55:40211 std::unique_ptr<MDnsConnection> connection_;
[email protected]245b164e2013-06-13 22:31:42212 };
213
[email protected]95b331b42013-12-02 06:26:31214 MDnsClientImpl();
Eric Orth026776a2019-01-18 00:13:28215
216 // Test constructor, takes a mock clock and mock timer.
217 MDnsClientImpl(base::Clock* clock,
218 std::unique_ptr<base::OneShotTimer> cleanup_timer);
219
Peter Boström407869b2021-10-07 04:42:48220 MDnsClientImpl(const MDnsClientImpl&) = delete;
221 MDnsClientImpl& operator=(const MDnsClientImpl&) = delete;
222
dcheng67be2b1f2014-10-27 21:47:29223 ~MDnsClientImpl() override;
[email protected]245b164e2013-06-13 22:31:42224
225 // MDnsClient implementation:
danakj22f90e72016-04-16 01:55:40226 std::unique_ptr<MDnsListener> CreateListener(
Avi Drissman13fc8932015-12-20 04:40:46227 uint16_t rrtype,
[email protected]245b164e2013-06-13 22:31:42228 const std::string& name,
mostynbba063d6032014-10-09 11:01:13229 MDnsListener::Delegate* delegate) override;
[email protected]245b164e2013-06-13 22:31:42230
danakj22f90e72016-04-16 01:55:40231 std::unique_ptr<MDnsTransaction> CreateTransaction(
Avi Drissman13fc8932015-12-20 04:40:46232 uint16_t rrtype,
[email protected]245b164e2013-06-13 22:31:42233 const std::string& name,
234 int flags,
mostynbba063d6032014-10-09 11:01:13235 const MDnsTransaction::ResultCallback& callback) override;
[email protected]245b164e2013-06-13 22:31:42236
Eric Orthe857ebb2019-03-13 23:02:07237 int StartListening(MDnsSocketFactory* socket_factory) override;
dcheng67be2b1f2014-10-27 21:47:29238 void StopListening() override;
239 bool IsListening() const override;
[email protected]245b164e2013-06-13 22:31:42240
241 Core* core() { return core_.get(); }
242
243 private:
tzik26331742017-12-07 07:28:33244 base::Clock* clock_;
tzik08d8d6e2018-07-09 04:11:47245 std::unique_ptr<base::OneShotTimer> cleanup_timer_;
[email protected]245b164e2013-06-13 22:31:42246
Eric Orth6cb27ea2019-05-03 16:31:04247 std::unique_ptr<Core> core_;
[email protected]245b164e2013-06-13 22:31:42248};
249
250class MDnsListenerImpl : public MDnsListener,
251 public base::SupportsWeakPtr<MDnsListenerImpl> {
252 public:
Avi Drissman13fc8932015-12-20 04:40:46253 MDnsListenerImpl(uint16_t rrtype,
[email protected]245b164e2013-06-13 22:31:42254 const std::string& name,
kmarshall3e740be2015-03-02 21:30:44255 base::Clock* clock,
[email protected]245b164e2013-06-13 22:31:42256 MDnsListener::Delegate* delegate,
257 MDnsClientImpl* client);
258
Peter Boström293b1342021-09-22 17:31:43259 MDnsListenerImpl(const MDnsListenerImpl&) = delete;
260 MDnsListenerImpl& operator=(const MDnsListenerImpl&) = delete;
261
dcheng67be2b1f2014-10-27 21:47:29262 ~MDnsListenerImpl() override;
[email protected]245b164e2013-06-13 22:31:42263
264 // MDnsListener implementation:
dcheng67be2b1f2014-10-27 21:47:29265 bool Start() override;
[email protected]245b164e2013-06-13 22:31:42266
[email protected]bdd6c3d2014-01-30 08:07:42267 // Actively refresh any received records.
dcheng67be2b1f2014-10-27 21:47:29268 void SetActiveRefresh(bool active_refresh) override;
[email protected]bdd6c3d2014-01-30 08:07:42269
dcheng67be2b1f2014-10-27 21:47:29270 const std::string& GetName() const override;
[email protected]245b164e2013-06-13 22:31:42271
Avi Drissman13fc8932015-12-20 04:40:46272 uint16_t GetType() const override;
[email protected]245b164e2013-06-13 22:31:42273
274 MDnsListener::Delegate* delegate() { return delegate_; }
275
276 // Alert the delegate of a record update.
[email protected]bdd6c3d2014-01-30 08:07:42277 void HandleRecordUpdate(MDnsCache::UpdateType update_type,
278 const RecordParsed* record_parsed);
[email protected]21df16962013-07-01 17:39:53279
280 // Alert the delegate of the existence of an Nsec record.
281 void AlertNsecRecord();
282
[email protected]245b164e2013-06-13 22:31:42283 private:
[email protected]bdd6c3d2014-01-30 08:07:42284 void ScheduleNextRefresh();
285 void DoRefresh();
286
Avi Drissman13fc8932015-12-20 04:40:46287 uint16_t rrtype_;
[email protected]245b164e2013-06-13 22:31:42288 std::string name_;
kmarshall3e740be2015-03-02 21:30:44289 base::Clock* clock_;
[email protected]245b164e2013-06-13 22:31:42290 MDnsClientImpl* client_;
291 MDnsListener::Delegate* delegate_;
292
[email protected]bdd6c3d2014-01-30 08:07:42293 base::Time last_update_;
Avi Drissman13fc8932015-12-20 04:40:46294 uint32_t ttl_;
[email protected]245b164e2013-06-13 22:31:42295 bool started_;
[email protected]bdd6c3d2014-01-30 08:07:42296 bool active_refresh_;
297
Alex Turner3ae74622020-11-25 15:42:24298 base::CancelableRepeatingClosure next_refresh_;
[email protected]245b164e2013-06-13 22:31:42299};
300
301class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>,
302 public MDnsTransaction,
303 public MDnsListener::Delegate {
304 public:
Avi Drissman13fc8932015-12-20 04:40:46305 MDnsTransactionImpl(uint16_t rrtype,
[email protected]245b164e2013-06-13 22:31:42306 const std::string& name,
307 int flags,
308 const MDnsTransaction::ResultCallback& callback,
309 MDnsClientImpl* client);
Peter Boström293b1342021-09-22 17:31:43310
311 MDnsTransactionImpl(const MDnsTransactionImpl&) = delete;
312 MDnsTransactionImpl& operator=(const MDnsTransactionImpl&) = delete;
313
dcheng67be2b1f2014-10-27 21:47:29314 ~MDnsTransactionImpl() override;
[email protected]245b164e2013-06-13 22:31:42315
316 // MDnsTransaction implementation:
dcheng67be2b1f2014-10-27 21:47:29317 bool Start() override;
[email protected]245b164e2013-06-13 22:31:42318
dcheng67be2b1f2014-10-27 21:47:29319 const std::string& GetName() const override;
Avi Drissman13fc8932015-12-20 04:40:46320 uint16_t GetType() const override;
[email protected]245b164e2013-06-13 22:31:42321
322 // MDnsListener::Delegate implementation:
dcheng67be2b1f2014-10-27 21:47:29323 void OnRecordUpdate(MDnsListener::UpdateType update,
324 const RecordParsed* record) override;
325 void OnNsecRecord(const std::string& name, unsigned type) override;
[email protected]245b164e2013-06-13 22:31:42326
dcheng67be2b1f2014-10-27 21:47:29327 void OnCachePurged() override;
[email protected]245b164e2013-06-13 22:31:42328
329 private:
330 bool is_active() { return !callback_.is_null(); }
331
332 void Reset();
333
334 // Trigger the callback and reset all related variables.
335 void TriggerCallback(MDnsTransaction::Result result,
336 const RecordParsed* record);
337
338 // Internal callback for when a cache record is found.
339 void CacheRecordFound(const RecordParsed* record);
340
341 // Signal the transactionis over and release all related resources.
342 void SignalTransactionOver();
343
[email protected]f3c09992013-06-25 00:40:48344 // Reads records from the cache and calls the callback for every
345 // record read.
346 void ServeRecordsFromCache();
347
348 // Send a query to the network and set up a timeout to time out the
349 // transaction. Returns false if it fails to start listening on the network
350 // or if it fails to send a query.
351 bool QueryAndListen();
352
Avi Drissman13fc8932015-12-20 04:40:46353 uint16_t rrtype_;
[email protected]245b164e2013-06-13 22:31:42354 std::string name_;
355 MDnsTransaction::ResultCallback callback_;
356
danakj22f90e72016-04-16 01:55:40357 std::unique_ptr<MDnsListener> listener_;
Steve Kobesf5bea3e2020-07-08 20:15:43358 base::CancelableOnceCallback<void()> timeout_;
[email protected]245b164e2013-06-13 22:31:42359
360 MDnsClientImpl* client_;
361
362 bool started_;
363 int flags_;
[email protected]245b164e2013-06-13 22:31:42364};
365
366} // namespace net
367#endif // NET_DNS_MDNS_CLIENT_IMPL_H_