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