OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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 | |
8 #include <map> | |
9 #include <string> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #include "base/cancelable_callback.h" | |
14 #include "base/observer_list.h" | |
15 #include "base/task_runner.h" | |
16 #include "base/time/clock.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/udp_socket.h" | |
22 | |
23 namespace net { | |
24 | |
25 class MDnsListenerImpl; | |
26 | |
27 // This class represents a connection to the network for multicast DNS clients. | |
28 // It reads data into DNSResponse objects and alerts the delegate that a packet | |
29 // has been received. | |
30 class MDnsConnection { | |
szym
2013/06/02 19:01:23
Since this is internal to mdns_client_impl, I don'
Noam Samuel
2013/06/03 17:57:55
This class is mocked in the tests to allow separat
szym
2013/06/03 18:38:30
Whelp! I didn't notice it. This CL is a bit large.
| |
31 public: | |
32 class Delegate { | |
33 public: | |
34 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|. | |
35 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0; | |
36 virtual ~Delegate() {} | |
37 }; | |
38 | |
39 // Start the connection. Will begin alerting the delegate of packets. | |
40 virtual bool Init() = 0; | |
41 | |
42 // Send a packet on both ipv4 and ipv6. | |
43 virtual bool Send(IOBuffer* buffer, unsigned size) = 0; | |
44 virtual ~MDnsConnection() {} | |
45 }; | |
46 | |
47 class MDnsConnectionFactory { | |
48 public: | |
49 virtual scoped_ptr<MDnsConnection> CreateConnection( | |
50 MDnsConnection::Delegate* delegate, | |
51 base::TaskRunner* task_runner) = 0; | |
52 | |
53 virtual ~MDnsConnectionFactory() {} | |
54 }; | |
55 | |
56 class MDnsClientImpl : public MDnsClient { | |
57 public: | |
58 // The core object exists while the MDnsClient is listening for MDnsPackets, | |
59 // and is deleted whenever the number of references for listening reachers | |
60 // zero. The message loop may hold weak pointers to it in order to ensure | |
61 // tasks scheduled on it are not delivered after it is destroyed. | |
62 class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate { | |
63 public: | |
64 Core(MDnsClientImpl* client, | |
65 MDnsConnectionFactory* connection_factory, | |
66 base::TaskRunner* task_runner, | |
67 base::Clock* clock); | |
68 virtual ~Core(); | |
69 | |
70 // Initialize the core. Returns true on success. | |
71 bool Init(); | |
72 | |
73 // Send a query with a specific rrtype and name. Returns true on success. | |
74 bool SendQuery(uint16 rrtype, std::string name); | |
75 | |
76 // Add/remove a listener to the list of listener. May cause network traffic | |
77 // if listener is active. | |
78 void AddListener(MDnsListenerImpl* listener, bool alert_existing_records); | |
79 void RemoveListener(MDnsListenerImpl* listener); | |
80 | |
81 // Query the cache for records of a specific type and name. | |
82 void QueryCache(uint16 rrtype, const std::string& name, | |
83 std::vector<const RecordParsed*>* records) const; | |
84 | |
85 // Parse the response and alert relevant listeners. | |
86 virtual void HandlePacket(DnsResponse* response, int bytes_read) OVERRIDE; | |
87 | |
88 private: | |
89 typedef std::pair<uint16, std::string> ListenerKey; | |
90 typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* > | |
91 ListenerMap; | |
92 | |
93 // Alert listeners of an update to the cache. | |
94 void AlertListeners(MDnsUpdateType update_type, | |
95 const ListenerKey& key, const RecordParsed* record); | |
96 | |
97 // Schedule a cleanup to a specific time, cancelling other cleanups. | |
98 void ScheduleCleanup(base::Time cleanup); | |
99 | |
100 // Clean up the cache and schedule a new cleanup. | |
101 void DoCleanup(); | |
102 | |
103 // Callback for when a record is removed from the cache. | |
104 void OnRecordRemoved(const RecordParsed* record); | |
105 | |
106 ListenerMap listeners_; | |
107 | |
108 MDnsClientImpl* client_; | |
109 MDnsCache cache_; | |
110 | |
111 base::CancelableCallback<void()> cleanup_callback_; | |
112 base::Time scheduled_cleanup_; | |
113 | |
114 scoped_refptr<base::TaskRunner> task_runner_; | |
115 base::Clock* clock_; | |
116 scoped_ptr<MDnsConnection> connection_; | |
117 | |
118 DISALLOW_COPY_AND_ASSIGN(Core); | |
119 }; | |
120 | |
121 MDnsClientImpl(); | |
122 | |
123 // Used only for testing. Lets users of this class decouple it from time | |
124 // dependence and network dependence. | |
125 MDnsClientImpl(base::Clock* clock, base::TaskRunner* task_runner, | |
126 MDnsConnectionFactory* connection_factory); | |
127 virtual ~MDnsClientImpl(); | |
128 | |
129 // Add delegate for RRType |rrtype| and name |name|. | |
130 // If |name| is an empty string, listen to all notification of type | |
131 // |rrtype|. | |
132 virtual scoped_ptr<MDnsListener> CreateListener( | |
133 uint16 rrtype, | |
134 const std::string& name, | |
135 bool active, | |
136 bool alert_existing_records, | |
137 MDnsListener::Delegate* delegate) OVERRIDE; | |
138 | |
139 // Create a transaction to Query MDNS for a single-value query | |
140 // (A, AAAA, TXT, and SRV) asynchronously. May defer to cache. | |
141 virtual scoped_ptr<MDnsTransaction> CreateTransaction( | |
142 uint16 rrtype, | |
143 const std::string& name, | |
144 const MDnsTransaction::ResultCallback& callback) OVERRIDE; | |
145 | |
146 // Functions for testing only. | |
147 bool IsListeningForTests(); | |
148 | |
149 private: | |
150 bool AddListenRef(); | |
151 void SubtractListenRef(); | |
152 void Shutdown(); | |
153 | |
154 scoped_ptr<Core> core_; | |
155 int listen_refs_; | |
156 | |
157 // Since we can either own or not own clock, use both a scoped_ptr and a ptr. | |
158 scoped_ptr<base::Clock> clock_owned_; | |
159 base::Clock* clock_; | |
160 | |
161 // Since we can either own or not own the connection_factory, use a scoped_ptr | |
162 // and a ptr. | |
163 scoped_ptr<MDnsConnectionFactory> connection_factory_owned_; | |
164 MDnsConnectionFactory* connection_factory_; | |
165 | |
166 scoped_refptr<base::TaskRunner> task_runner_; | |
167 | |
168 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl); | |
169 }; | |
170 | |
171 class MDnsListenerImpl : public MDnsListener, | |
172 public base::SupportsWeakPtr<MDnsListenerImpl> { | |
173 public: | |
174 MDnsListenerImpl(uint16 rrtype, | |
175 const std::string& name, | |
176 bool active, | |
177 bool alert_existing_records, | |
178 MDnsListener::Delegate* delegate, | |
179 MDnsClientImpl::Core* core); | |
180 | |
181 // Destroying the listener stops listening. | |
182 virtual ~MDnsListenerImpl(); | |
183 | |
184 // Get the host or service name for this query. | |
185 // Return an empty string for no name. | |
186 virtual const std::string& GetName() const OVERRIDE; | |
187 | |
188 // Get the type for this query (SRV, TXT, A, AAA, etc) | |
189 virtual uint16 GetType() const OVERRIDE; | |
190 | |
191 virtual bool IsActive() const OVERRIDE; | |
192 | |
193 // Applies only to listeners with names. Will send out a query for new | |
194 // information. |force_refresh_cache| will force a refresh of all cached | |
195 // entities. | |
196 virtual bool SendQuery(bool force_refresh_cache) OVERRIDE; | |
197 | |
198 // Applies only to listeners with names. Query mDNS cache synchronously for | |
199 // either single- or multi- valued records. | |
200 virtual bool QueryCache( | |
201 std::vector<const RecordParsed*>* records) const OVERRIDE; | |
202 | |
203 MDnsListener::Delegate* delegate() { return delegate_; } | |
204 | |
205 void AlertDelegate(MDnsUpdateType update_type, | |
206 const RecordParsed* record_parsed); | |
207 private: | |
208 uint16 rrtype_; | |
209 std::string name_; | |
210 bool active_; | |
211 MDnsClientImpl::Core* parent_; | |
212 MDnsListener::Delegate* delegate_; | |
213 | |
214 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl); | |
215 }; | |
216 | |
217 class MDnsTransactionImpl : public MDnsTransaction, | |
218 public base::SupportsWeakPtr<MDnsTransactionImpl>, | |
219 public MDnsListener::Delegate { | |
220 public: | |
221 MDnsTransactionImpl(uint16 rrtype, | |
222 const std::string& name, | |
223 const MDnsTransaction::ResultCallback& callback, | |
224 base::TaskRunner* task_runner); | |
225 virtual ~MDnsTransactionImpl(); | |
226 | |
227 // Start the transaction. Returns true on success. | |
228 bool Init(MDnsClientImpl* client, | |
229 MDnsClientImpl::Core* core); | |
230 | |
231 // MDnsListener::Delegate implementation | |
232 virtual void OnRecordUpdate(MDnsUpdateType update, | |
233 const RecordParsed* record) OVERRIDE; | |
234 virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE; | |
235 | |
236 virtual const std::string& GetName() const OVERRIDE; | |
237 virtual uint16 GetType() const OVERRIDE; | |
238 | |
239 private: | |
240 // Trigger the callback and reset all related variables. | |
241 void TriggerCallback(MDnsTransactionResult result, | |
242 const RecordParsed* record); | |
243 | |
244 // Internal callback for when a cache record is found. | |
245 void CacheRecordFound(const RecordParsed* record); | |
246 | |
247 // Callback for when the transaction times out. | |
248 void OnTimedOut(); | |
249 | |
250 uint16 rrtype_; | |
251 std::string name_; | |
252 MDnsTransaction::ResultCallback callback_; | |
253 | |
254 bool triggered_; | |
255 scoped_ptr<MDnsListener> listener_; | |
256 base::CancelableCallback<void()> timeout_; | |
257 scoped_refptr<base::TaskRunner> task_runner_; | |
258 | |
259 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl); | |
260 }; | |
261 | |
262 // This implementation of MDnsConnection handles connecting to both IPv4 and | |
263 // IPv6. | |
264 class MDnsConnectionImpl : public base::SupportsWeakPtr<MDnsConnectionImpl>, | |
265 public MDnsConnection { | |
266 public: | |
267 MDnsConnectionImpl(MDnsConnection::Delegate* delegate, | |
268 base::TaskRunner* task_runner); | |
269 virtual ~MDnsConnectionImpl(); | |
270 | |
271 virtual bool Init() OVERRIDE; | |
272 virtual bool Send(IOBuffer* buffer, unsigned size) OVERRIDE; | |
273 | |
274 private: | |
275 // Bind a socket with a specific address size to a specific multicast group | |
276 // and port 5353. | |
277 bool BindSocket(UDPSocket* socket, | |
278 int addr_size, | |
279 const char* multicast_group); | |
280 | |
281 // Callback for handling a datagram being recieved on either ipv4 or ipv6. | |
282 // Responsible for ensuring we request another packet from the network. | |
283 void OnDatagramReceived(UDPSocket* socket, | |
284 DnsResponse* response, | |
285 IPEndPoint* recv_addr, | |
286 int bytes_read); | |
287 | |
288 // Request another packet from the network. | |
289 bool ReceiveNextPacket(UDPSocket* socket, | |
290 DnsResponse* response, | |
291 IPEndPoint* recv_addr); | |
292 | |
293 // Callback for when sending a query has finished. | |
294 void SendDone(int sent); | |
295 | |
296 // The IPEndPoints for sending/recieving packets on IPv4 and IPv6. | |
297 IPEndPoint GetIPv4SendEndpoint(); | |
298 IPEndPoint GetIPv6SendEndpoint(); | |
299 | |
300 scoped_ptr<UDPSocket> socket_ipv4_; | |
301 scoped_ptr<UDPSocket> socket_ipv6_; | |
302 | |
303 scoped_ptr<DnsResponse> response_ipv4_; | |
304 scoped_ptr<DnsResponse> response_ipv6_; | |
305 | |
306 // The address from which the last packet was recieved. | |
307 IPEndPoint recv_addr_ipv4_; | |
308 IPEndPoint recv_addr_ipv6_; | |
309 | |
310 MDnsConnection::Delegate* delegate_; | |
311 | |
312 scoped_refptr<base::TaskRunner> task_runner_; | |
313 | |
314 DISALLOW_COPY_AND_ASSIGN(MDnsConnectionImpl); | |
315 }; | |
316 | |
317 class MDnsConnectionImplFactory : public MDnsConnectionFactory { | |
318 public: | |
319 MDnsConnectionImplFactory(); | |
320 virtual ~MDnsConnectionImplFactory(); | |
321 | |
322 virtual scoped_ptr<MDnsConnection> CreateConnection( | |
323 MDnsConnection::Delegate* delegate, | |
324 base::TaskRunner* task_runner) OVERRIDE; | |
325 | |
326 private: | |
327 DISALLOW_COPY_AND_ASSIGN(MDnsConnectionImplFactory); | |
328 }; | |
329 | |
330 } | |
331 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_ | |
OLD | NEW |