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: 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 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; 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(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); 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::CancelableCallback<void()> 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 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 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); 216 217 // Alert the delegate of the existence of an Nsec record. 218 void AlertNsecRecord(); 219 220 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 230 class 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 269 // 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 278 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_ 295