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/observer_list.h" 15#include "net/base/io_buffer.h" 16#include "net/base/ip_endpoint.h" 17#include "net/dns/mdns_cache.h" 18#include "net/dns/mdns_client.h" 19#include "net/udp/datagram_server_socket.h" 20#include "net/udp/udp_server_socket.h" 21#include "net/udp/udp_socket.h" 22 23namespace net { 24 25// A connection to the network for multicast DNS clients. It reads data into 26// DnsResponse objects and alerts the delegate that a packet has been received. 27class NET_EXPORT_PRIVATE MDnsConnection { 28 public: 29 class SocketFactory { 30 public: 31 virtual ~SocketFactory() {} 32 33 virtual scoped_ptr<DatagramServerSocket> CreateSocket() = 0; 34 35 static scoped_ptr<SocketFactory> CreateDefault(); 36 }; 37 38 class Delegate { 39 public: 40 // Handle an mDNS packet buffered in |response| with a size of |bytes_read|. 41 virtual void HandlePacket(DnsResponse* response, int bytes_read) = 0; 42 virtual void OnConnectionError(int error) = 0; 43 virtual ~Delegate() {} 44 }; 45 46 explicit MDnsConnection(SocketFactory* socket_factory, 47 MDnsConnection::Delegate* delegate); 48 49 virtual ~MDnsConnection(); 50 51 int Init(); 52 int Send(IOBuffer* buffer, unsigned size); 53 54 private: 55 class SocketHandler { 56 public: 57 SocketHandler(MDnsConnection* connection, 58 const IPEndPoint& multicast_addr, 59 SocketFactory* socket_factory); 60 ~SocketHandler(); 61 int DoLoop(int rv); 62 int Start(); 63 64 int Send(IOBuffer* buffer, unsigned size); 65 66 private: 67 int BindSocket(); 68 void OnDatagramReceived(int rv); 69 70 // Callback for when sending a query has finished. 71 void SendDone(int rv); 72 73 scoped_ptr<DatagramServerSocket> socket_; 74 75 MDnsConnection* connection_; 76 IPEndPoint recv_addr_; 77 scoped_ptr<DnsResponse> response_; 78 IPEndPoint multicast_addr_; 79 }; 80 81 // Callback for handling a datagram being received on either ipv4 or ipv6. 82 void OnDatagramReceived(DnsResponse* response, 83 const IPEndPoint& recv_addr, 84 int bytes_read); 85 86 void OnError(SocketHandler* loop, int error); 87 88 IPEndPoint GetMDnsIPEndPoint(const char* address); 89 90 SocketHandler socket_handler_ipv4_; 91 SocketHandler socket_handler_ipv6_; 92 93 Delegate* delegate_; 94 95 DISALLOW_COPY_AND_ASSIGN(MDnsConnection); 96}; 97 98class MDnsListenerImpl; 99 100class 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 Core(MDnsClientImpl* client, 109 MDnsConnection::SocketFactory* socket_factory); 110 virtual ~Core(); 111 112 // Initialize the core. Returns true on success. 113 bool Init(); 114 115 // Send a query with a specific rrtype and name. Returns true on success. 116 bool SendQuery(uint16 rrtype, std::string name); 117 118 // Add/remove a listener to the list of listeners. 119 void AddListener(MDnsListenerImpl* listener); 120 void RemoveListener(MDnsListenerImpl* listener); 121 122 // Query the cache for records of a specific type and name. 123 void QueryCache(uint16 rrtype, const std::string& name, 124 std::vector<const RecordParsed*>* records) const; 125 126 // Parse the response and alert relevant listeners. 127 virtual void HandlePacket(DnsResponse* response, int bytes_read) OVERRIDE; 128 129 virtual void OnConnectionError(int error) OVERRIDE; 130 131 private: 132 typedef std::pair<std::string, uint16> ListenerKey; 133 typedef std::map<ListenerKey, ObserverList<MDnsListenerImpl>* > 134 ListenerMap; 135 136 // Alert listeners of an update to the cache. 137 void AlertListeners(MDnsListener::UpdateType update_type, 138 const ListenerKey& key, const RecordParsed* record); 139 140 // Schedule a cache cleanup to a specific time, cancelling other cleanups. 141 void ScheduleCleanup(base::Time cleanup); 142 143 // Clean up the cache and schedule a new cleanup. 144 void DoCleanup(); 145 146 // Callback for when a record is removed from the cache. 147 void OnRecordRemoved(const RecordParsed* record); 148 149 void NotifyNsecRecord(const RecordParsed* record); 150 151 // Delete and erase the observer list for |key|. Only deletes the observer 152 // list if is empty. 153 void CleanupObserverList(const ListenerKey& key); 154 155 ListenerMap listeners_; 156 157 MDnsClientImpl* client_; 158 MDnsCache cache_; 159 160 base::CancelableCallback<void()> cleanup_callback_; 161 base::Time scheduled_cleanup_; 162 163 scoped_ptr<MDnsConnection> connection_; 164 165 DISALLOW_COPY_AND_ASSIGN(Core); 166 }; 167 168 explicit MDnsClientImpl( 169 scoped_ptr<MDnsConnection::SocketFactory> socket_factory_); 170 virtual ~MDnsClientImpl(); 171 172 // MDnsClient implementation: 173 virtual scoped_ptr<MDnsListener> CreateListener( 174 uint16 rrtype, 175 const std::string& name, 176 MDnsListener::Delegate* delegate) OVERRIDE; 177 178 virtual scoped_ptr<MDnsTransaction> CreateTransaction( 179 uint16 rrtype, 180 const std::string& name, 181 int flags, 182 const MDnsTransaction::ResultCallback& callback) OVERRIDE; 183 184 virtual bool StartListening() OVERRIDE; 185 virtual void StopListening() OVERRIDE; 186 virtual bool IsListening() const OVERRIDE; 187 188 Core* core() { return core_.get(); } 189 190 private: 191 scoped_ptr<Core> core_; 192 193 scoped_ptr<MDnsConnection::SocketFactory> socket_factory_; 194 195 DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl); 196}; 197 198class MDnsListenerImpl : public MDnsListener, 199 public base::SupportsWeakPtr<MDnsListenerImpl> { 200 public: 201 MDnsListenerImpl(uint16 rrtype, 202 const std::string& name, 203 MDnsListener::Delegate* delegate, 204 MDnsClientImpl* client); 205 206 virtual ~MDnsListenerImpl(); 207 208 // MDnsListener implementation: 209 virtual bool Start() OVERRIDE; 210 211 virtual const std::string& GetName() const OVERRIDE; 212 213 virtual uint16 GetType() const OVERRIDE; 214 215 MDnsListener::Delegate* delegate() { return delegate_; } 216 217 // Alert the delegate of a record update. 218 void AlertDelegate(MDnsListener::UpdateType update_type, 219 const RecordParsed* record_parsed); 220 221 // Alert the delegate of the existence of an Nsec record. 222 void AlertNsecRecord(); 223 224 private: 225 uint16 rrtype_; 226 std::string name_; 227 MDnsClientImpl* client_; 228 MDnsListener::Delegate* delegate_; 229 230 bool started_; 231 DISALLOW_COPY_AND_ASSIGN(MDnsListenerImpl); 232}; 233 234class MDnsTransactionImpl : public base::SupportsWeakPtr<MDnsTransactionImpl>, 235 public MDnsTransaction, 236 public MDnsListener::Delegate { 237 public: 238 MDnsTransactionImpl(uint16 rrtype, 239 const std::string& name, 240 int flags, 241 const MDnsTransaction::ResultCallback& callback, 242 MDnsClientImpl* client); 243 virtual ~MDnsTransactionImpl(); 244 245 // MDnsTransaction implementation: 246 virtual bool Start() OVERRIDE; 247 248 virtual const std::string& GetName() const OVERRIDE; 249 virtual uint16 GetType() const OVERRIDE; 250 251 // MDnsListener::Delegate implementation: 252 virtual void OnRecordUpdate(MDnsListener::UpdateType update, 253 const RecordParsed* record) OVERRIDE; 254 virtual void OnNsecRecord(const std::string& name, unsigned type) OVERRIDE; 255 256 virtual void OnCachePurged() OVERRIDE; 257 258 private: 259 bool is_active() { return !callback_.is_null(); } 260 261 void Reset(); 262 263 // Trigger the callback and reset all related variables. 264 void TriggerCallback(MDnsTransaction::Result result, 265 const RecordParsed* record); 266 267 // Internal callback for when a cache record is found. 268 void CacheRecordFound(const RecordParsed* record); 269 270 // Signal the transactionis over and release all related resources. 271 void SignalTransactionOver(); 272 273 // Reads records from the cache and calls the callback for every 274 // record read. 275 void ServeRecordsFromCache(); 276 277 // Send a query to the network and set up a timeout to time out the 278 // transaction. Returns false if it fails to start listening on the network 279 // or if it fails to send a query. 280 bool QueryAndListen(); 281 282 uint16 rrtype_; 283 std::string name_; 284 MDnsTransaction::ResultCallback callback_; 285 286 scoped_ptr<MDnsListener> listener_; 287 base::CancelableCallback<void()> timeout_; 288 289 MDnsClientImpl* client_; 290 291 bool started_; 292 int flags_; 293 294 DISALLOW_COPY_AND_ASSIGN(MDnsTransactionImpl); 295}; 296 297} // namespace net 298#endif // NET_DNS_MDNS_CLIENT_IMPL_H_ 299