• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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/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"
23 
24 namespace net {
25 
26 class MDnsSocketFactoryImpl : public MDnsSocketFactory {
27  public:
MDnsSocketFactoryImpl()28   MDnsSocketFactoryImpl() {};
~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 
38 // 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.
40 class NET_EXPORT_PRIVATE MDnsConnection {
41  public:
42   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;
~Delegate()47     virtual ~Delegate() {}
48   };
49 
50   explicit MDnsConnection(MDnsConnection::Delegate* delegate);
51   virtual ~MDnsConnection();
52 
53   // Both methods return true if at least one of the socket handlers succeeded.
54   bool Init(MDnsSocketFactory* socket_factory);
55   void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
56 
57  private:
58   class SocketHandler {
59    public:
60     SocketHandler(scoped_ptr<DatagramServerSocket> socket,
61                   MDnsConnection* connection);
62     ~SocketHandler();
63 
64     int Start();
65     void Send(const scoped_refptr<IOBuffer>& buffer, unsigned size);
66 
67    private:
68     int DoLoop(int rv);
69     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_;
75     MDnsConnection* connection_;
76     IPEndPoint recv_addr_;
77     DnsResponse response_;
78     IPEndPoint multicast_addr_;
79     bool send_in_progress_;
80     std::queue<std::pair<scoped_refptr<IOBuffer>, unsigned> > send_queue_;
81 
82     DISALLOW_COPY_AND_ASSIGN(SocketHandler);
83   };
84 
85   // Callback for handling a datagram being received on either ipv4 or ipv6.
86   void OnDatagramReceived(DnsResponse* response,
87                           const IPEndPoint& recv_addr,
88                           int bytes_read);
89 
90   void PostOnError(SocketHandler* loop, int rv);
91   void OnError(int rv);
92 
93   // Only socket handlers which successfully bound and started are kept.
94   ScopedVector<SocketHandler> socket_handlers_;
95 
96   Delegate* delegate_;
97 
98   base::WeakPtrFactory<MDnsConnection> weak_ptr_factory_;
99 
100   DISALLOW_COPY_AND_ASSIGN(MDnsConnection);
101 };
102 
103 class MDnsListenerImpl;
104 
105 class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
106  public:
107   // The core object exists while the MDnsClient is listening, and is deleted
108   // whenever the number of listeners reaches zero. The deletion happens
109   // asychronously, so destroying the last listener does not immediately
110   // invalidate the core.
111   class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate {
112    public:
113     explicit Core(MDnsClientImpl* client);
114     virtual ~Core();
115 
116     // Initialize the core. Returns true on success.
117     bool Init(MDnsSocketFactory* socket_factory);
118 
119     // Send a query with a specific rrtype and name. Returns true on success.
120     bool SendQuery(uint16 rrtype, std::string name);
121 
122     // Add/remove a listener to the list of listeners.
123     void AddListener(MDnsListenerImpl* listener);
124     void RemoveListener(MDnsListenerImpl* listener);
125 
126     // Query the cache for records of a specific type and name.
127     void QueryCache(uint16 rrtype, const std::string& name,
128                     std::vector<const RecordParsed*>* records) const;
129 
130     // Parse the response and alert relevant listeners.
131     virtual void HandlePacket(DnsResponse* response, int bytes_read) OVERRIDE;
132 
133     virtual void OnConnectionError(int error) OVERRIDE;
134 
135    private:
136     typedef std::pair<std::string, uint16> ListenerKey;
137     typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* >
138     ListenerMap;
139 
140     // Alert listeners of an update to the cache.
141     void AlertListeners(MDnsCache::UpdateType update_type,
142                         const ListenerKey& key, const RecordParsed* record);
143 
144     // Schedule a cache cleanup to a specific time, cancelling other cleanups.
145     void ScheduleCleanup(base::Time cleanup);
146 
147     // Clean up the cache and schedule a new cleanup.
148     void DoCleanup();
149 
150     // Callback for when a record is removed from the cache.
151     void OnRecordRemoved(const RecordParsed* record);
152 
153     void NotifyNsecRecord(const RecordParsed* record);
154 
155     // Delete and erase the observer list for |key|. Only deletes the observer
156     // list if is empty.
157     void CleanupObserverList(const ListenerKey& key);
158 
159     ListenerMap listeners_;
160 
161     MDnsClientImpl* client_;
162     MDnsCache cache_;
163 
164     base::CancelableClosure cleanup_callback_;
165     base::Time scheduled_cleanup_;
166 
167     scoped_ptr<MDnsConnection> connection_;
168 
169     DISALLOW_COPY_AND_ASSIGN(Core);
170   };
171 
172   MDnsClientImpl();
173   virtual ~MDnsClientImpl();
174 
175   // MDnsClient implementation:
176   virtual scoped_ptr<MDnsListener> CreateListener(
177       uint16 rrtype,
178       const std::string& name,
179       MDnsListener::Delegate* delegate) OVERRIDE;
180 
181   virtual scoped_ptr<MDnsTransaction> CreateTransaction(
182       uint16 rrtype,
183       const std::string& name,
184       int flags,
185       const MDnsTransaction::ResultCallback& callback) OVERRIDE;
186 
187   virtual bool StartListening(MDnsSocketFactory* socket_factory) OVERRIDE;
188   virtual void StopListening() OVERRIDE;
189   virtual bool IsListening() const OVERRIDE;
190 
core()191   Core* core() { return core_.get(); }
192 
193  private:
194   scoped_ptr<Core> core_;
195 
196   DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl);
197 };
198 
199 class MDnsListenerImpl : public MDnsListener,
200                          public base::SupportsWeakPtr<MDnsListenerImpl> {
201  public:
202   MDnsListenerImpl(uint16 rrtype,
203                    const std::string& name,
204                    MDnsListener::Delegate* delegate,
205                    MDnsClientImpl* client);
206 
207   virtual ~MDnsListenerImpl();
208 
209   // MDnsListener implementation:
210   virtual bool Start() OVERRIDE;
211 
212   // Actively refresh any received records.
213   virtual void SetActiveRefresh(bool active_refresh) OVERRIDE;
214 
215   virtual const std::string& GetName() const OVERRIDE;
216 
217   virtual uint16 GetType() const OVERRIDE;
218 
delegate()219   MDnsListener::Delegate* delegate() { return delegate_; }
220 
221   // Alert the delegate of a record update.
222   void HandleRecordUpdate(MDnsCache::UpdateType update_type,
223                           const RecordParsed* record_parsed);
224 
225   // Alert the delegate of the existence of an Nsec record.
226   void AlertNsecRecord();
227 
228  private:
229   void ScheduleNextRefresh();
230   void DoRefresh();
231 
232   uint16 rrtype_;
233   std::string name_;
234   MDnsClientImpl* client_;
235   MDnsListener::Delegate* delegate_;
236 
237   base::Time last_update_;
238   uint32 ttl_;
239   bool started_;
240   bool active_refresh_;
241 
242   base::CancelableClosure next_refresh_;
243   DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl);
244 };
245 
246 class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>,
247                             public MDnsTransaction,
248                             public MDnsListener::Delegate {
249  public:
250   MDnsTransactionImpl(uint16 rrtype,
251                       const std::string& name,
252                       int flags,
253                       const MDnsTransaction::ResultCallback& callback,
254                       MDnsClientImpl* client);
255   virtual ~MDnsTransactionImpl();
256 
257   // MDnsTransaction implementation:
258   virtual bool Start() OVERRIDE;
259 
260   virtual const std::string& GetName() const OVERRIDE;
261   virtual uint16 GetType() const OVERRIDE;
262 
263   // MDnsListener::Delegate implementation:
264   virtual void OnRecordUpdate(MDnsListener::UpdateType update,
265                               const RecordParsed* record) OVERRIDE;
266   virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE;
267 
268   virtual void OnCachePurged() OVERRIDE;
269 
270  private:
is_active()271   bool is_active() { return !callback_.is_null(); }
272 
273   void Reset();
274 
275   // Trigger the callback and reset all related variables.
276   void TriggerCallback(MDnsTransaction::Result result,
277                        const RecordParsed* record);
278 
279   // Internal callback for when a cache record is found.
280   void CacheRecordFound(const RecordParsed* record);
281 
282   // Signal the transactionis over and release all related resources.
283   void SignalTransactionOver();
284 
285   // Reads records from the cache and calls the callback for every
286   // record read.
287   void ServeRecordsFromCache();
288 
289   // Send a query to the network and set up a timeout to time out the
290   // transaction. Returns false if it fails to start listening on the network
291   // or if it fails to send a query.
292   bool QueryAndListen();
293 
294   uint16 rrtype_;
295   std::string name_;
296   MDnsTransaction::ResultCallback callback_;
297 
298   scoped_ptr<MDnsListener> listener_;
299   base::CancelableCallback<void()> timeout_;
300 
301   MDnsClientImpl* client_;
302 
303   bool started_;
304   int flags_;
305 
306   DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl);
307 };
308 
309 }  // namespace net
310 #endif  // NET_DNS_MDNS_CLIENT_IMPL_H_
311