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 bool Send(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 int Send(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 80 DISALLOW_COPY_AND_ASSIGN(SocketHandler); 81 }; 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 90 // Only socket handlers which successfully bound and started are kept. 91 ScopedVector<SocketHandler> socket_handlers_; 92 93 Delegate* delegate_; 94 95 DISALLOW_COPY_AND_ASSIGN(MDnsConnection); 96 }; 97 98 class MDnsListenerImpl; 99 100 class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { 101 public: 102 // 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. 106 class Core : public base::SupportsWeakPtr<Core>, MDnsConnection::Delegate { 107 public: 108 explicit Core(MDnsClientImpl* client); 109 virtual ~Core(); 110 111 // Initialize the core. Returns true on success. 112 bool Init(MDnsSocketFactory* socket_factory); 113 114 // Send a query with a specific rrtype and name. Returns true on success. 115 bool SendQuery(uint16 rrtype, std::string name); 116 117 // Add/remove a listener to the list of listeners. 118 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: 131 typedef std::pair<std::string, uint16> ListenerKey; 132 typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* > 133 ListenerMap; 134 135 // Alert listeners of an update to the cache. 136 void AlertListeners(MDnsCache::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); 147 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); 153 154 ListenerMap listeners_; 155 156 MDnsClientImpl* client_; 157 MDnsCache cache_; 158 159 base::CancelableClosure cleanup_callback_; 160 base::Time scheduled_cleanup_; 161 162 scoped_ptr<MDnsConnection> connection_; 163 164 DISALLOW_COPY_AND_ASSIGN(Core); 165 }; 166 167 MDnsClientImpl(); 168 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 182 virtual bool StartListening(MDnsSocketFactory* socket_factory) OVERRIDE; 183 virtual void StopListening() OVERRIDE; 184 virtual bool IsListening() const OVERRIDE; 185 core()186 Core* core() { return core_.get(); } 187 188 private: 189 scoped_ptr<Core> core_; 190 191 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl); 192 }; 193 194 class 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 // Actively refresh any received records. 208 virtual void SetActiveRefresh(bool active_refresh) OVERRIDE; 209 210 virtual const std::string& GetName() const OVERRIDE; 211 212 virtual uint16 GetType() const OVERRIDE; 213 delegate()214 MDnsListener::Delegate* delegate() { return delegate_; } 215 216 // Alert the delegate of a record update. 217 void HandleRecordUpdate(MDnsCache::UpdateType update_type, 218 const RecordParsed* record_parsed); 219 220 // Alert the delegate of the existence of an Nsec record. 221 void AlertNsecRecord(); 222 223 private: 224 void ScheduleNextRefresh(); 225 void DoRefresh(); 226 227 uint16 rrtype_; 228 std::string name_; 229 MDnsClientImpl* client_; 230 MDnsListener::Delegate* delegate_; 231 232 base::Time last_update_; 233 uint32 ttl_; 234 bool started_; 235 bool active_refresh_; 236 237 base::CancelableClosure next_refresh_; 238 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl); 239 }; 240 241 class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>, 242 public MDnsTransaction, 243 public MDnsListener::Delegate { 244 public: 245 MDnsTransactionImpl(uint16 rrtype, 246 const std::string& name, 247 int flags, 248 const MDnsTransaction::ResultCallback& callback, 249 MDnsClientImpl* client); 250 virtual ~MDnsTransactionImpl(); 251 252 // MDnsTransaction implementation: 253 virtual bool Start() OVERRIDE; 254 255 virtual const std::string& GetName() const OVERRIDE; 256 virtual uint16 GetType() const OVERRIDE; 257 258 // MDnsListener::Delegate implementation: 259 virtual void OnRecordUpdate(MDnsListener::UpdateType update, 260 const RecordParsed* record) OVERRIDE; 261 virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE; 262 263 virtual void OnCachePurged() OVERRIDE; 264 265 private: is_active()266 bool is_active() { return !callback_.is_null(); } 267 268 void Reset(); 269 270 // Trigger the callback and reset all related variables. 271 void TriggerCallback(MDnsTransaction::Result result, 272 const RecordParsed* record); 273 274 // Internal callback for when a cache record is found. 275 void CacheRecordFound(const RecordParsed* record); 276 277 // Signal the transactionis over and release all related resources. 278 void SignalTransactionOver(); 279 280 // Reads records from the cache and calls the callback for every 281 // record read. 282 void ServeRecordsFromCache(); 283 284 // Send a query to the network and set up a timeout to time out the 285 // transaction. Returns false if it fails to start listening on the network 286 // or if it fails to send a query. 287 bool QueryAndListen(); 288 289 uint16 rrtype_; 290 std::string name_; 291 MDnsTransaction::ResultCallback callback_; 292 293 scoped_ptr<MDnsListener> listener_; 294 base::CancelableCallback<void()> timeout_; 295 296 MDnsClientImpl* client_; 297 298 bool started_; 299 int flags_; 300 301 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl); 302 }; 303 304 } // namespace net 305 #endif // NET_DNS_MDNS_CLIENT_IMPL_H_ 306