[go: nahoru, domu]

blob: f75598560ab43c0634f656c109630daee1b6e2b4 [file] [log] [blame]
noamsml@chromium.org245b164e2013-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
8#include <map>
9#include <string>
10#include <utility>
11#include <vector>
12
13#include "base/cancelable_callback.h"
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:1114#include "base/memory/scoped_vector.h"
noamsml@chromium.org245b164e2013-06-13 22:31:4215#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"
23
24namespace net {
25
vitalybuka@chromium.org95b331b42013-12-02 06:26:3126class MDnsSocketFactoryImpl : public MDnsSocketFactory {
27 public:
28 MDnsSocketFactoryImpl() {};
29 virtual ~MDnsSocketFactoryImpl() {};
30
31 virtual void CreateSockets(
32 ScopedVector<DatagramServerSocket>* sockets) OVERRIDE;
33
34 private:
35 DISALLOW_COPY_AND_ASSIGN(MDnsSocketFactoryImpl);
36};
37
noamsml@chromium.org245b164e2013-06-13 22:31:4238// A connection to the network for multicast DNS clients. It reads data into
39// DnsResponse objects and alerts the delegate that a packet has been received.
noamsml@chromium.orgba77c27f2013-07-02 22:34:3240class NET_EXPORT_PRIVATE MDnsConnection {
noamsml@chromium.org245b164e2013-06-13 22:31:4241 public:
noamsml@chromium.org245b164e2013-06-13 22:31:4242 class Delegate {
43 public:
44 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|.
45 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0;
46 virtual void OnConnectionError(int error) = 0;
47 virtual ~Delegate() {}
48 };
49
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:1150 explicit MDnsConnection(MDnsConnection::Delegate* delegate);
noamsml@chromium.org245b164e2013-06-13 22:31:4251 virtual ~MDnsConnection();
52
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:1153 // Both methods return true if at least one of the socket handlers succeeded.
vitalybuka@chromium.org95b331b42013-12-02 06:26:3154 bool Init(MDnsSocketFactory* socket_factory);
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:1155 bool Send(IOBuffer* buffer, unsigned size);
noamsml@chromium.org245b164e2013-06-13 22:31:4256
57 private:
58 class SocketHandler {
59 public:
vitalybuka@chromium.org95b331b42013-12-02 06:26:3160 SocketHandler(scoped_ptr<DatagramServerSocket> socket,
61 MDnsConnection* connection);
noamsml@chromium.org245b164e2013-06-13 22:31:4262 ~SocketHandler();
noamsml@chromium.org245b164e2013-06-13 22:31:4263
vitalybuka@chromium.org95b331b42013-12-02 06:26:3164 int Start();
noamsml@chromium.org245b164e2013-06-13 22:31:4265 int Send(IOBuffer* buffer, unsigned size);
66
67 private:
vitalybuka@chromium.org03dd94252013-09-01 23:25:3168 int DoLoop(int rv);
noamsml@chromium.org245b164e2013-06-13 22:31:4269 void OnDatagramReceived(int rv);
70
71 // Callback for when sending a query has finished.
72 void SendDone(int rv);
73
74 scoped_ptr<DatagramServerSocket> socket_;
noamsml@chromium.org245b164e2013-06-13 22:31:4275 MDnsConnection* connection_;
76 IPEndPoint recv_addr_;
vitalybuka@chromium.org95b331b42013-12-02 06:26:3177 DnsResponse response_;
noamsml@chromium.org245b164e2013-06-13 22:31:4278 IPEndPoint multicast_addr_;
vitalybuka@chromium.org95b331b42013-12-02 06:26:3179
80 DISALLOW_COPY_AND_ASSIGN(SocketHandler);
noamsml@chromium.org245b164e2013-06-13 22:31:4281 };
82
83 // Callback for handling a datagram being received on either ipv4 or ipv6.
84 void OnDatagramReceived(DnsResponse* response,
85 const IPEndPoint& recv_addr,
86 int bytes_read);
87
88 void OnError(SocketHandler* loop, int error);
89
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:1190 // Only socket handlers which successfully bound and started are kept.
91 ScopedVector<SocketHandler> socket_handlers_;
noamsml@chromium.org245b164e2013-06-13 22:31:4292
93 Delegate* delegate_;
94
95 DISALLOW_COPY_AND_ASSIGN(MDnsConnection);
96};
97
98class MDnsListenerImpl;
99
noamsml@chromium.orgba77c27f2013-07-02 22:34:32100class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
noamsml@chromium.org245b164e2013-06-13 22:31:42101 public:
noamsml@chromium.org21df16962013-07-01 17:39:53102 // The core object exists while the MDnsClient is listening, and is deleted
103 // whenever the number of listeners reaches zero. The deletion happens
104 // asychronously, so destroying the last listener does not immediately
105 // invalidate the core.
noamsml@chromium.org245b164e2013-06-13 22:31:42106 class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate {
107 public:
vitalybuka@chromium.orge4411fbe2013-09-26 21:10:11108 explicit Core(MDnsClientImpl* client);
noamsml@chromium.org245b164e2013-06-13 22:31:42109 virtual ~Core();
110
111 // Initialize the core. Returns true on success.
vitalybuka@chromium.org95b331b42013-12-02 06:26:31112 bool Init(MDnsSocketFactory* socket_factory);
noamsml@chromium.org245b164e2013-06-13 22:31:42113
114 // Send a query with a specific rrtype and name. Returns true on success.
115 bool SendQuery(uint16 rrtype, std::string name);
116
noamsml@chromium.org21df16962013-07-01 17:39:53117 // Add/remove a listener to the list of listeners.
noamsml@chromium.org245b164e2013-06-13 22:31:42118 void AddListener(MDnsListenerImpl* listener);
119 void RemoveListener(MDnsListenerImpl* listener);
120
121 // Query the cache for records of a specific type and name.
122 void QueryCache(uint16 rrtype, const std::string& name,
123 std::vector<const RecordParsed*>* records) const;
124
125 // Parse the response and alert relevant listeners.
126 virtual void HandlePacket(DnsResponse* response, int bytes_read) OVERRIDE;
127
128 virtual void OnConnectionError(int error) OVERRIDE;
129
130 private:
noamsml@chromium.org21df16962013-07-01 17:39:53131 typedef std::pair<std::string, uint16> ListenerKey;
noamsml@chromium.org245b164e2013-06-13 22:31:42132 typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* >
133 ListenerMap;
134
135 // Alert listeners of an update to the cache.
136 void AlertListeners(MDnsListener::UpdateType update_type,
137 const ListenerKey& key, const RecordParsed* record);
138
139 // Schedule a cache cleanup to a specific time, cancelling other cleanups.
140 void ScheduleCleanup(base::Time cleanup);
141
142 // Clean up the cache and schedule a new cleanup.
143 void DoCleanup();
144
145 // Callback for when a record is removed from the cache.
146 void OnRecordRemoved(const RecordParsed* record);
noamsml@chromium.org21df16962013-07-01 17:39:53147
148 void NotifyNsecRecord(const RecordParsed* record);
149
150 // Delete and erase the observer list for |key|. Only deletes the observer
151 // list if is empty.
152 void CleanupObserverList(const ListenerKey& key);
noamsml@chromium.org245b164e2013-06-13 22:31:42153
154 ListenerMap listeners_;
155
156 MDnsClientImpl* client_;
157 MDnsCache cache_;
158
159 base::CancelableCallback<void()> cleanup_callback_;
160 base::Time scheduled_cleanup_;
161
162 scoped_ptr<MDnsConnection> connection_;
163
164 DISALLOW_COPY_AND_ASSIGN(Core);
165 };
166
vitalybuka@chromium.org95b331b42013-12-02 06:26:31167 MDnsClientImpl();
noamsml@chromium.org245b164e2013-06-13 22:31:42168 virtual ~MDnsClientImpl();
169
170 // MDnsClient implementation:
171 virtual scoped_ptr<MDnsListener> CreateListener(
172 uint16 rrtype,
173 const std::string& name,
174 MDnsListener::Delegate* delegate) OVERRIDE;
175
176 virtual scoped_ptr<MDnsTransaction> CreateTransaction(
177 uint16 rrtype,
178 const std::string& name,
179 int flags,
180 const MDnsTransaction::ResultCallback& callback) OVERRIDE;
181
vitalybuka@chromium.org95b331b42013-12-02 06:26:31182 virtual bool StartListening(MDnsSocketFactory* socket_factory) OVERRIDE;
noamsml@chromium.org9c61d252013-07-02 23:26:22183 virtual void StopListening() OVERRIDE;
184 virtual bool IsListening() const OVERRIDE;
noamsml@chromium.org245b164e2013-06-13 22:31:42185
186 Core* core() { return core_.get(); }
187
188 private:
noamsml@chromium.org245b164e2013-06-13 22:31:42189 scoped_ptr<Core> core_;
noamsml@chromium.org245b164e2013-06-13 22:31:42190
191 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl);
192};
193
194class MDnsListenerImpl : public MDnsListener,
195 public base::SupportsWeakPtr<MDnsListenerImpl> {
196 public:
197 MDnsListenerImpl(uint16 rrtype,
198 const std::string& name,
199 MDnsListener::Delegate* delegate,
200 MDnsClientImpl* client);
201
202 virtual ~MDnsListenerImpl();
203
204 // MDnsListener implementation:
205 virtual bool Start() OVERRIDE;
206
207 virtual const std::string& GetName() const OVERRIDE;
208
209 virtual uint16 GetType() const OVERRIDE;
210
211 MDnsListener::Delegate* delegate() { return delegate_; }
212
213 // Alert the delegate of a record update.
214 void AlertDelegate(MDnsListener::UpdateType update_type,
215 const RecordParsed* record_parsed);
noamsml@chromium.org21df16962013-07-01 17:39:53216
217 // Alert the delegate of the existence of an Nsec record.
218 void AlertNsecRecord();
219
noamsml@chromium.org245b164e2013-06-13 22:31:42220 private:
221 uint16 rrtype_;
222 std::string name_;
223 MDnsClientImpl* client_;
224 MDnsListener::Delegate* delegate_;
225
226 bool started_;
227 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl);
228};
229
230class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>,
231 public MDnsTransaction,
232 public MDnsListener::Delegate {
233 public:
234 MDnsTransactionImpl(uint16 rrtype,
235 const std::string& name,
236 int flags,
237 const MDnsTransaction::ResultCallback& callback,
238 MDnsClientImpl* client);
239 virtual ~MDnsTransactionImpl();
240
241 // MDnsTransaction implementation:
242 virtual bool Start() OVERRIDE;
243
244 virtual const std::string& GetName() const OVERRIDE;
245 virtual uint16 GetType() const OVERRIDE;
246
247 // MDnsListener::Delegate implementation:
248 virtual void OnRecordUpdate(MDnsListener::UpdateType update,
249 const RecordParsed* record) OVERRIDE;
250 virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE;
251
252 virtual void OnCachePurged() OVERRIDE;
253
254 private:
255 bool is_active() { return !callback_.is_null(); }
256
257 void Reset();
258
259 // Trigger the callback and reset all related variables.
260 void TriggerCallback(MDnsTransaction::Result result,
261 const RecordParsed* record);
262
263 // Internal callback for when a cache record is found.
264 void CacheRecordFound(const RecordParsed* record);
265
266 // Signal the transactionis over and release all related resources.
267 void SignalTransactionOver();
268
noamsml@chromium.orgf3c09992013-06-25 00:40:48269 // Reads records from the cache and calls the callback for every
270 // record read.
271 void ServeRecordsFromCache();
272
273 // Send a query to the network and set up a timeout to time out the
274 // transaction. Returns false if it fails to start listening on the network
275 // or if it fails to send a query.
276 bool QueryAndListen();
277
noamsml@chromium.org245b164e2013-06-13 22:31:42278 uint16 rrtype_;
279 std::string name_;
280 MDnsTransaction::ResultCallback callback_;
281
282 scoped_ptr<MDnsListener> listener_;
283 base::CancelableCallback<void()> timeout_;
284
285 MDnsClientImpl* client_;
286
287 bool started_;
288 int flags_;
289
290 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl);
291};
292
293} // namespace net
294#endif // NET_DNS_MDNS_CLIENT_IMPL_H_