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 "net/base/io_buffer.h" | |
16 #include "net/base/ip_endpoint.h" | |
17 #include "net/dns/mdns_cache.h" | |
18 #include "net/dns/mdns_client.h" | |
19 #include "net/udp/datagram_server_socket.h" | |
20 #include "net/udp/udp_server_socket.h" | |
21 #include "net/udp/udp_socket.h" | |
22 | |
23 | |
24 namespace net { | |
25 | |
26 class MDnsListenerImpl; | |
27 | |
28 // This class represents a connection to the network for multicast DNS clients. | |
szym
2013/06/07 16:40:02
nit: No need for "This class represents".
Noam Samuel
2013/06/07 23:54:43
Done.
| |
29 // It reads data into DNSResponse objects and alerts the delegate that a packet | |
szym
2013/06/07 16:40:02
nit: DnsResponse
Noam Samuel
2013/06/07 23:54:43
Done.
| |
30 // has been received. | |
31 class MDnsConnection { | |
32 public: | |
33 class Delegate { | |
34 public: | |
35 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|. | |
36 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0; | |
37 virtual ~Delegate() {} | |
szym
2013/06/07 16:40:02
In MDnsConnectionImpl you moved error handling to
Noam Samuel
2013/06/07 23:54:43
Added tests for MDnsConnectionImpl using mocked ob
| |
38 }; | |
39 | |
40 // Start the connection. Will begin alerting the delegate of packets. | |
41 virtual bool Init() = 0; | |
szym
2013/06/07 16:40:02
nit: Returns?
Noam Samuel
2013/06/07 23:54:43
Done.
| |
42 | |
43 // Send a packet on both ipv4 and ipv6. | |
44 virtual bool Send(IOBuffer* buffer, unsigned size) = 0; | |
szym
2013/06/07 16:40:02
nit: Returns?
Noam Samuel
2013/06/07 23:54:43
Done.
| |
45 virtual ~MDnsConnection() {} | |
46 }; | |
47 | |
48 class MDnsConnectionFactory { | |
49 public: | |
50 virtual scoped_ptr<MDnsConnection> CreateConnection( | |
51 MDnsConnection::Delegate* delegate) = 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 virtual ~Core(); | |
67 | |
68 // Initialize the core. Returns true on success. | |
69 bool Init(); | |
70 | |
71 // Send a query with a specific rrtype and name. Returns true on success. | |
72 bool SendQuery(uint16 rrtype, std::string name); | |
73 | |
74 // Add/remove a listener to the list of listener. May cause network traffic | |
75 // if listener is active. | |
76 void AddListener(MDnsListenerImpl* listener); | |
77 void RemoveListener(MDnsListenerImpl* listener); | |
78 | |
79 // Query the cache for records of a specific type and name. | |
80 void QueryCache(uint16 rrtype, const std::string& name, | |
81 std::vector<const RecordParsed*>* records) const; | |
82 | |
83 // Parse the response and alert relevant listeners. | |
84 virtual void HandlePacket(DnsResponse* response, int bytes_read) OVERRIDE; | |
85 | |
86 private: | |
87 typedef std::pair<uint16, std::string> ListenerKey; | |
88 typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* > | |
89 ListenerMap; | |
90 | |
91 // Alert listeners of an update to the cache. | |
92 void AlertListeners(MDnsUpdateType update_type, | |
93 const ListenerKey& key, const RecordParsed* record); | |
94 | |
95 // Schedule a cleanup to a specific time, cancelling other cleanups. | |
96 void ScheduleCleanup(base::Time cleanup); | |
97 | |
98 // Clean up the cache and schedule a new cleanup. | |
99 void DoCleanup(); | |
100 | |
101 // Callback for when a record is removed from the cache. | |
102 void OnRecordRemoved(const RecordParsed* record); | |
103 | |
104 ListenerMap listeners_; | |
105 | |
106 MDnsClientImpl* client_; | |
107 MDnsCache cache_; | |
108 | |
109 base::CancelableCallback<void()> cleanup_callback_; | |
110 base::Time scheduled_cleanup_; | |
111 | |
112 scoped_ptr<MDnsConnection> connection_; | |
113 | |
114 DISALLOW_COPY_AND_ASSIGN(Core); | |
115 }; | |
116 | |
117 MDnsClientImpl(); | |
118 | |
119 // Used only for testing. Lets users of this class decouple it from time | |
120 // dependence and network dependence. | |
121 explicit MDnsClientImpl(MDnsConnectionFactory* connection_factory); | |
122 virtual ~MDnsClientImpl(); | |
123 | |
124 // Add delegate for RRType |rrtype| and name |name|. | |
125 // If |name| is an empty string, listen to all notification of type | |
126 // |rrtype|. | |
127 virtual scoped_ptr<MDnsListener> CreateListener( | |
128 uint16 rrtype, | |
129 const std::string& name, | |
130 MDnsListener::Delegate* delegate) OVERRIDE; | |
131 | |
132 // Create a transaction to Query MDNS for a single-value query | |
133 // (A, AAAA, TXT, and SRV) asynchronously. May defer to cache. | |
134 virtual scoped_ptr<MDnsTransaction> CreateTransaction( | |
135 uint16 rrtype, | |
136 const std::string& name, | |
137 int flags, | |
138 const MDnsTransaction::ResultCallback& callback) OVERRIDE; | |
139 | |
140 | |
141 // Functions for testing only. | |
142 bool IsListeningForTests(); | |
143 | |
144 bool AddListenRef(); | |
145 void SubtractListenRef(); | |
146 | |
147 Core* core() { return core_.get(); } | |
148 | |
149 private: | |
150 void Shutdown(); | |
151 | |
152 scoped_ptr<Core> core_; | |
153 int listen_refs_; | |
154 | |
155 // Since we can either own or not own the connection_factory, use a scoped_ptr | |
156 // and a ptr. | |
157 scoped_ptr<MDnsConnectionFactory> connection_factory_owned_; | |
158 MDnsConnectionFactory* connection_factory_; | |
159 | |
160 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl); | |
161 }; | |
162 | |
163 class MDnsListenerImpl : public MDnsListener, | |
164 public base::SupportsWeakPtr<MDnsListenerImpl> { | |
165 public: | |
166 MDnsListenerImpl(uint16 rrtype, | |
167 const std::string& name, | |
168 MDnsListener::Delegate* delegate, | |
169 MDnsClientImpl* client); | |
170 | |
171 // Destroying the listener stops listening. | |
172 virtual ~MDnsListenerImpl(); | |
173 | |
174 // Start the listener. Returns true on success. | |
szym
2013/06/07 16:40:02
You don't really need to copy comments on implemen
Noam Samuel
2013/06/07 23:54:43
Done.
| |
175 virtual bool Start() OVERRIDE; | |
176 | |
177 // Get the host or service name for this query. | |
178 // Return an empty string for no name. | |
179 virtual const std::string& GetName() const OVERRIDE; | |
180 | |
181 // Get the type for this query (SRV, TXT, A, AAA, etc) | |
182 virtual uint16 GetType() const OVERRIDE; | |
183 | |
184 MDnsListener::Delegate* delegate() { return delegate_; } | |
185 | |
186 void AlertDelegate(MDnsUpdateType update_type, | |
szym
2013/06/07 16:40:02
nit: Needs a comment.
Noam Samuel
2013/06/07 23:54:43
Done.
| |
187 const RecordParsed* record_parsed); | |
188 private: | |
189 uint16 rrtype_; | |
190 std::string name_; | |
191 MDnsClientImpl* client_; | |
192 MDnsListener::Delegate* delegate_; | |
193 | |
194 bool started_; | |
195 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl); | |
196 }; | |
197 | |
198 class MDnsTransactionImpl : public MDnsTransaction, | |
199 public base::SupportsWeakPtr<MDnsTransactionImpl>, | |
szym
2013/06/07 16:40:02
nit: Don't put SupportsWeakPtr in between two inte
Noam Samuel
2013/06/07 23:54:43
Done.
| |
200 public MDnsListener::Delegate { | |
201 public: | |
202 MDnsTransactionImpl(uint16 rrtype, | |
203 const std::string& name, | |
204 int flags, | |
205 const MDnsTransaction::ResultCallback& callback, | |
206 MDnsClientImpl* client); | |
207 virtual ~MDnsTransactionImpl(); | |
208 | |
209 // Start the transaction. Returns true on success. | |
szym
2013/06/07 16:40:02
// MDnsTransaction implementation:
Noam Samuel
2013/06/07 23:54:43
Done.
| |
210 virtual bool Start() OVERRIDE; | |
211 | |
212 // MDnsListener::Delegate implementation | |
213 virtual void OnRecordUpdate(MDnsUpdateType update, | |
214 const RecordParsed* record) OVERRIDE; | |
215 virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE; | |
216 | |
217 virtual void OnCachePurged() OVERRIDE; | |
218 | |
219 virtual const std::string& GetName() const OVERRIDE; | |
szym
2013/06/07 16:40:02
Keep the methods from different interfaces separat
Noam Samuel
2013/06/07 23:54:43
Done.
| |
220 virtual uint16 GetType() const OVERRIDE; | |
221 | |
222 bool is_valid() { return !callback_.is_null(); } | |
szym
2013/06/07 16:40:02
I'd suggest is_active() or is_pending(), since not
Noam Samuel
2013/06/07 23:54:43
Done.
| |
223 | |
224 void Reset(); | |
225 | |
226 private: | |
227 // Trigger the callback and reset all related variables. | |
228 void TriggerCallback(MDnsTransactionResult result, | |
229 const RecordParsed* record); | |
230 | |
231 // Internal callback for when a cache record is found. | |
232 void CacheRecordFound(const RecordParsed* record); | |
233 | |
234 // Signal the transactionis over and release all related resources. | |
235 void SignalTransactionOver(); | |
236 | |
237 uint16 rrtype_; | |
238 std::string name_; | |
239 MDnsTransaction::ResultCallback callback_; | |
240 | |
241 scoped_ptr<MDnsListener> listener_; | |
242 base::CancelableCallback<void()> timeout_; | |
243 | |
244 MDnsClientImpl* client_; | |
245 | |
246 bool started_; | |
247 int flags_; | |
248 | |
249 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl); | |
250 }; | |
251 | |
252 // This implementation of MDnsConnection handles connecting to both IPv4 and | |
253 // IPv6. | |
254 class MDnsConnectionImpl : public MDnsConnection { | |
255 public: | |
256 explicit MDnsConnectionImpl(MDnsConnection::Delegate* delegate); | |
257 virtual ~MDnsConnectionImpl(); | |
258 | |
259 virtual bool Init() OVERRIDE; | |
260 virtual bool Send(IOBuffer* buffer, unsigned size) OVERRIDE; | |
261 | |
262 private: | |
263 class RecvLoop { | |
szym
2013/06/07 16:40:02
This could be better structured, by moving socket
Noam Samuel
2013/06/07 23:54:43
Done.
| |
264 public: | |
265 RecvLoop(DatagramServerSocket* socket, MDnsConnectionImpl* connection); | |
266 ~RecvLoop(); | |
267 void DoLoop(int rv); | |
268 | |
269 private: | |
270 void OnDatagramReceived(int rv); | |
271 | |
272 DatagramServerSocket* socket_; | |
273 MDnsConnectionImpl* connection_; | |
274 IPEndPoint recv_addr_; | |
275 scoped_ptr<DnsResponse> response_; | |
276 }; | |
277 // Bind a socket with a specific address size to a specific multicast group | |
278 // and port 5353. | |
279 bool BindSocket(DatagramServerSocket* socket, | |
280 int addr_size, | |
281 const char* multicast_group); | |
282 | |
283 // Callback for handling a datagram being recieved on either ipv4 or ipv6. | |
284 // Responsible for ensuring we request another packet from the network. | |
285 void OnDatagramReceived(DatagramServerSocket* socket, | |
286 DnsResponse* response, | |
287 IPEndPoint* recv_addr, | |
288 int bytes_read); | |
289 | |
290 void OnError(RecvLoop* loop, DatagramServerSocket* socket, int error); | |
291 | |
292 // Callback for when sending a query has finished. | |
293 void SendDone(int sent); | |
294 | |
295 // The IPEndPoints for sending/recieving packets on IPv4 and IPv6. | |
296 IPEndPoint GetIPv4SendEndpoint(); | |
297 IPEndPoint GetIPv6SendEndpoint(); | |
298 | |
299 scoped_ptr<DatagramServerSocket> socket_ipv4_; | |
300 scoped_ptr<DatagramServerSocket> socket_ipv6_; | |
301 | |
302 RecvLoop loop_ipv4_; | |
303 RecvLoop loop_ipv6_; | |
304 | |
305 MDnsConnection::Delegate* delegate_; | |
306 | |
307 DISALLOW_COPY_AND_ASSIGN(MDnsConnectionImpl); | |
308 }; | |
309 | |
310 class MDnsConnectionImplFactory : public MDnsConnectionFactory { | |
311 public: | |
312 MDnsConnectionImplFactory(); | |
313 virtual ~MDnsConnectionImplFactory(); | |
314 | |
315 virtual scoped_ptr<MDnsConnection> CreateConnection( | |
316 MDnsConnection::Delegate* delegate) OVERRIDE; | |
317 | |
318 private: | |
319 DISALLOW_COPY_AND_ASSIGN(MDnsConnectionImplFactory); | |
320 }; | |
321 | |
322 } | |
323 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_ | |
OLD | NEW |