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_H_
6#define NET_DNS_MDNS_CLIENT_H_
7
8#include <string>
9#include <vector>
10
11#include "base/callback.h"
12#include "net/base/ip_endpoint.h"
13#include "net/dns/dns_query.h"
14#include "net/dns/dns_response.h"
15#include "net/dns/record_parsed.h"
16
17namespace net {
18
19class DatagramServerSocket;
20class RecordParsed;
21
22// Represents a one-time record lookup. A transaction takes one
23// associated callback (see |MDnsClient::CreateTransaction|) and calls it
24// whenever a matching record has been found, either from the cache or
25// by querying the network (it may choose to query either or both based on its
26// creation flags, see MDnsTransactionFlags). Network-based transactions will
27// time out after a reasonable number of seconds.
28class NET_EXPORT MDnsTransaction {
29 public:
30  // Used to signify what type of result the transaction has received.
31  enum Result {
32    // Passed whenever a record is found.
33    RESULT_RECORD,
34    // The transaction is done. Applies to non-single-valued transactions. Is
35    // called when the transaction has finished (this is the last call to the
36    // callback).
37    RESULT_DONE,
38    // No results have been found. Applies to single-valued transactions. Is
39    // called when the transaction has finished without finding any results.
40    // For transactions that use the network, this happens when a timeout
41    // occurs, for transactions that are cache-only, this happens when no
42    // results are in the cache.
43    RESULT_NO_RESULTS,
44    // Called when an NSec record is read for this transaction's
45    // query. This means there cannot possibly be a record of the type
46    // and name for this transaction.
47    RESULT_NSEC
48  };
49
50  // Used when creating an MDnsTransaction.
51  enum Flags {
52    // Transaction should return only one result, and stop listening after it.
53    // Note that single result transactions will signal when their timeout is
54    // reached, whereas multi-result transactions will not.
55    SINGLE_RESULT = 1 << 0,
56    // Query the cache or the network. May both be used. One must be present.
57    QUERY_CACHE = 1 << 1,
58    QUERY_NETWORK = 1 << 2,
59    // TODO(noamsml): Add flag for flushing cache when feature is implemented
60    // Mask of all possible flags on MDnsTransaction.
61    FLAG_MASK = (1 << 3) - 1,
62  };
63
64  typedef base::Callback<void(Result, const RecordParsed*)>
65  ResultCallback;
66
67  // Destroying the transaction cancels it.
68  virtual ~MDnsTransaction() {}
69
70  // Start the transaction. Return true on success. Cache-based transactions
71  // will execute the callback synchronously.
72  virtual bool Start() = 0;
73
74  // Get the host or service name for the transaction.
75  virtual const std::string& GetName() const = 0;
76
77  // Get the type for this transaction (SRV, TXT, A, AAA, etc)
78  virtual uint16 GetType() const = 0;
79};
80
81// A listener listens for updates regarding a specific record or set of records.
82// Created by the MDnsClient (see |MDnsClient::CreateListener|) and used to keep
83// track of listeners.
84class NET_EXPORT MDnsListener {
85 public:
86  // Used in the MDnsListener delegate to signify what type of change has been
87  // made to a record.
88  enum UpdateType {
89    RECORD_ADDED,
90    RECORD_CHANGED,
91    RECORD_REMOVED
92  };
93
94  class Delegate {
95   public:
96    virtual ~Delegate() {}
97
98    // Called when a record is added, removed or updated.
99    virtual void OnRecordUpdate(UpdateType update,
100                                const RecordParsed* record) = 0;
101
102    // Called when a record is marked nonexistent by an NSEC record.
103    virtual void OnNsecRecord(const std::string& name, unsigned type) = 0;
104
105    // Called when the cache is purged (due, for example, ot the network
106    // disconnecting).
107    virtual void OnCachePurged() = 0;
108  };
109
110  // Destroying the listener stops listening.
111  virtual ~MDnsListener() {}
112
113  // Start the listener. Return true on success.
114  virtual bool Start() = 0;
115
116  // Actively refresh any received records.
117  virtual void SetActiveRefresh(bool active_refresh) = 0;
118
119  // Get the host or service name for this query.
120  // Return an empty string for no name.
121  virtual const std::string& GetName() const = 0;
122
123  // Get the type for this query (SRV, TXT, A, AAA, etc)
124  virtual uint16 GetType() const = 0;
125};
126
127// Creates bound datagram sockets ready to use by MDnsClient.
128class NET_EXPORT MDnsSocketFactory {
129 public:
130  virtual ~MDnsSocketFactory() {}
131  virtual void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) = 0;
132
133  static scoped_ptr<MDnsSocketFactory> CreateDefault();
134};
135
136// Listens for Multicast DNS on the local network. You can access information
137// regarding multicast DNS either by creating an |MDnsListener| to be notified
138// of new records, or by creating an |MDnsTransaction| to look up the value of a
139// specific records. When all listeners and active transactions are destroyed,
140// the client stops listening on the network and destroys the cache.
141class NET_EXPORT MDnsClient {
142 public:
143  virtual ~MDnsClient() {}
144
145  // Create listener object for RRType |rrtype| and name |name|.
146  virtual scoped_ptr<MDnsListener> CreateListener(
147      uint16 rrtype,
148      const std::string& name,
149      MDnsListener::Delegate* delegate) = 0;
150
151  // Create a transaction that can be used to query either the MDns cache, the
152  // network, or both for records of type |rrtype| and name |name|. |flags| is
153  // defined by MDnsTransactionFlags.
154  virtual scoped_ptr<MDnsTransaction> CreateTransaction(
155      uint16 rrtype,
156      const std::string& name,
157      int flags,
158      const MDnsTransaction::ResultCallback& callback) = 0;
159
160  virtual bool StartListening(MDnsSocketFactory* factory) = 0;
161
162  // Do not call this inside callbacks from related MDnsListener and
163  // MDnsTransaction objects.
164  virtual void StopListening() = 0;
165  virtual bool IsListening() const = 0;
166
167  // Create the default MDnsClient
168  static scoped_ptr<MDnsClient> CreateDefault();
169};
170
171NET_EXPORT IPEndPoint GetMDnsIPEndPoint(AddressFamily address_family);
172
173typedef std::vector<std::pair<uint32, AddressFamily> > InterfaceIndexFamilyList;
174// Returns pairs of interface and address family to bind. Current
175// implementation returns unique list of all available interfaces.
176NET_EXPORT InterfaceIndexFamilyList GetMDnsInterfacesToBind();
177
178// Create sockets, binds socket to MDns endpoint, and sets multicast interface
179// and joins multicast group on for |interface_index|.
180// Returns NULL if failed.
181NET_EXPORT scoped_ptr<DatagramServerSocket> CreateAndBindMDnsSocket(
182    AddressFamily address_family,
183    uint32 interface_index);
184
185}  // namespace net
186
187#endif  // NET_DNS_MDNS_CLIENT_H_
188