Home | History | Annotate | Download | only in dns
      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   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 
    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 
    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:
    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