blob: f9f8fb12fff8737da10e489e742d5078541fa00b [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_DNS_MDNS_CLIENT_H_
#define NET_DNS_MDNS_CLIENT_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/callback.h"
#include "base/time/time.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_response.h"
#include "net/dns/record_parsed.h"
namespace net {
class DatagramServerSocket;
class NetLog;
class RecordParsed;
// Represents a one-time record lookup. A transaction takes one
// associated callback (see |MDnsClient::CreateTransaction|) and calls it
// whenever a matching record has been found, either from the cache or
// by querying the network (it may choose to query either or both based on its
// creation flags, see MDnsTransactionFlags). Network-based transactions will
// time out after a reasonable number of seconds.
class NET_EXPORT MDnsTransaction {
public:
static const base::TimeDelta kTransactionTimeout;
// Used to signify what type of result the transaction has received.
enum Result {
// Passed whenever a record is found.
RESULT_RECORD,
// The transaction is done. Applies to non-single-valued transactions. Is
// called when the transaction has finished (this is the last call to the
// callback).
RESULT_DONE,
// No results have been found. Applies to single-valued transactions. Is
// called when the transaction has finished without finding any results.
// For transactions that use the network, this happens when a timeout
// occurs, for transactions that are cache-only, this happens when no
// results are in the cache.
RESULT_NO_RESULTS,
// Called when an NSec record is read for this transaction's
// query. This means there cannot possibly be a record of the type
// and name for this transaction.
RESULT_NSEC
};
// Used when creating an MDnsTransaction.
enum Flags {
// Transaction should return only one result, and stop listening after it.
// Note that single result transactions will signal when their timeout is
// reached, whereas multi-result transactions will not.
SINGLE_RESULT = 1 << 0,
// Query the cache or the network. May both be used. One must be present.
QUERY_CACHE = 1 << 1,
QUERY_NETWORK = 1 << 2,
// TODO(noamsml): Add flag for flushing cache when feature is implemented
// Mask of all possible flags on MDnsTransaction.
FLAG_MASK = (1 << 3) - 1,
};
typedef base::RepeatingCallback<void(Result, const RecordParsed*)>
ResultCallback;
// Destroying the transaction cancels it.
virtual ~MDnsTransaction() = default;
// Start the transaction. Return true on success. Cache-based transactions
// will execute the callback synchronously.
virtual bool Start() = 0;
// Get the host or service name for the transaction.
virtual const std::string& GetName() const = 0;
// Get the type for this transaction (SRV, TXT, A, AAA, etc)
virtual uint16_t GetType() const = 0;
};
// A listener listens for updates regarding a specific record or set of records.
// Created by the MDnsClient (see |MDnsClient::CreateListener|) and used to keep
// track of listeners.
//
// TODO(ericorth@chromium.org): Consider moving this inside MDnsClient to better
// organize the namespace and avoid confusion with
// net::HostResolver::MdnsListener.
class NET_EXPORT MDnsListener {
public:
// Used in the MDnsListener delegate to signify what type of change has been
// made to a record.
enum UpdateType {
RECORD_ADDED,
RECORD_CHANGED,
RECORD_REMOVED
};
class Delegate {
public:
virtual ~Delegate() = default;
// Called when a record is added, removed or updated.
virtual void OnRecordUpdate(UpdateType update,
const RecordParsed* record) = 0;
// Called when a record is marked nonexistent by an NSEC record.
virtual void OnNsecRecord(const std::string& name, unsigned type) = 0;
// Called when the cache is purged (due, for example, ot the network
// disconnecting).
virtual void OnCachePurged() = 0;
};
// Destroying the listener stops listening.
virtual ~MDnsListener() = default;
// Start the listener. Return true on success.
virtual bool Start() = 0;
// Actively refresh any received records.
virtual void SetActiveRefresh(bool active_refresh) = 0;
// Get the host or service name for this query.
// Return an empty string for no name.
virtual const std::string& GetName() const = 0;
// Get the type for this query (SRV, TXT, A, AAA, etc)
virtual uint16_t GetType() const = 0;
};
// Creates bound datagram sockets ready to use by MDnsClient.
class NET_EXPORT MDnsSocketFactory {
public:
virtual ~MDnsSocketFactory() = default;
virtual void CreateSockets(
std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) = 0;
static std::unique_ptr<MDnsSocketFactory> CreateDefault();
};
// Listens for Multicast DNS on the local network. You can access information
// regarding multicast DNS either by creating an |MDnsListener| to be notified
// of new records, or by creating an |MDnsTransaction| to look up the value of a
// specific records. When all listeners and active transactions are destroyed,
// the client stops listening on the network and destroys the cache.
class NET_EXPORT MDnsClient {
public:
virtual ~MDnsClient() = default;
// Create listener object for RRType |rrtype| and name |name|.
virtual std::unique_ptr<MDnsListener> CreateListener(
uint16_t rrtype,
const std::string& name,
MDnsListener::Delegate* delegate) = 0;
// Create a transaction that can be used to query either the MDns cache, the
// network, or both for records of type |rrtype| and name |name|. |flags| is
// defined by MDnsTransactionFlags.
virtual std::unique_ptr<MDnsTransaction> CreateTransaction(
uint16_t rrtype,
const std::string& name,
int flags,
const MDnsTransaction::ResultCallback& callback) = 0;
virtual int StartListening(MDnsSocketFactory* factory) = 0;
// Do not call this inside callbacks from related MDnsListener and
// MDnsTransaction objects.
virtual void StopListening() = 0;
virtual bool IsListening() const = 0;
// Create the default MDnsClient
static std::unique_ptr<MDnsClient> CreateDefault();
};
// Gets the endpoint for the multicast group a socket should join to receive
// MDNS messages. Such sockets should also bind to the endpoint from
// GetMDnsReceiveEndPoint().
//
// This is also the endpoint messages should be sent to to send MDNS messages.
NET_EXPORT IPEndPoint GetMDnsGroupEndPoint(AddressFamily address_family);
// Gets the endpoint sockets should be bound to to receive MDNS messages. Such
// sockets should also join the multicast group from GetMDnsGroupEndPoint().
NET_EXPORT IPEndPoint GetMDnsReceiveEndPoint(AddressFamily address_family);
typedef std::vector<std::pair<uint32_t, AddressFamily>>
InterfaceIndexFamilyList;
// Returns pairs of interface and address family to bind. Current
// implementation returns unique list of all available interfaces.
NET_EXPORT InterfaceIndexFamilyList GetMDnsInterfacesToBind();
// Create sockets, binds socket to MDns endpoint, and sets multicast interface
// and joins multicast group on for |interface_index|.
// Returns NULL if failed.
NET_EXPORT std::unique_ptr<DatagramServerSocket> CreateAndBindMDnsSocket(
AddressFamily address_family,
uint32_t interface_index,
NetLog* net_log);
} // namespace net
#endif // NET_DNS_MDNS_CLIENT_H_