dns_client.h 6.22 KB
Newer Older
1
// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
2
//
3 4 5
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 7 8 9 10 11 12 13 14 15

#ifndef DNS_CLIENT_H
#define DNS_CLIENT_H

#include <d2/d2_update_message.h>

#include <asiolink/io_service.h>
#include <util/buffer.h>

#include <asiodns/io_fetch.h>
16
#include <dns/tsig.h>
17 18 19 20

namespace isc {
namespace d2 {

21 22 23 24
class DNSClient;
typedef boost::shared_ptr<DNSClient> DNSClientPtr;

/// DNSClient class implementation.
25 26
class DNSClientImpl;

27 28 29 30
/// @brief The @c DNSClient class handles communication with the DNS server.
///
/// Communication with the DNS server is asynchronous. Caller must provide a
/// callback, which will be invoked when the response from the DNS server is
31
/// received, a timeout has occurred or IO service has been stopped for any
32 33 34 35 36 37 38 39 40
/// reason. The caller-supplied callback is called by the internal callback
/// operator implemented by @c DNSClient. This callback is responsible for
/// initializing the @c D2UpdateMessage instance which encapsulates the response
/// from the DNS. This initialization does not take place if the response from
/// DNS is not received.
///
/// Caller must supply a pointer to the @c D2UpdateMessage object, which will
/// encapsulate DNS response, through class constructor. An exception will be
/// thrown if the pointer is not initialized by the caller.
41 42 43 44 45 46 47 48
///
/// @todo Ultimately, this class will support both TCP and UDP Transport.
/// Currently only UDP is supported and can be specified as a preferred
/// protocol. @c DNSClient constructor will throw an exception if TCP is
/// specified. Once both protocols are supported, the @c DNSClient logic will
/// try to obey caller's preference. However, it may use the other protocol if
/// on its own discretion, when there is a legitimate reason to do so. For
/// example, if communication with the server using preferred protocol fails.
49
class DNSClient {
50 51
public:

52 53 54 55 56 57 58
    /// @brief Transport layer protocol used by a DNS Client to communicate
    /// with a server.
    enum Protocol {
        UDP,
        TCP
    };

59 60 61 62 63 64 65 66 67
    /// @brief A status code of the DNSClient.
    enum Status {
        SUCCESS,           ///< Response received and is ok.
        TIMEOUT,           ///< No response, timeout.
        IO_STOPPED,        ///< IO was stopped.
        INVALID_RESPONSE,  ///< Response received but invalid.
        OTHER              ///< Other, unclassified error.
    };

68 69
    /// @brief Callback for the @c DNSClient class.
    ///
70
    /// This is an abstract class which represents the external callback for the
71 72 73 74 75 76 77 78 79 80
    /// @c DNSClient. Caller must implement this class and supply its instance
    /// in the @c DNSClient constructor to get callbacks when the DNS Update
    /// exchange is complete (@see @c DNSClient).
    class Callback {
    public:
        /// @brief Virtual destructor.
        virtual ~Callback() { }

        /// @brief Function operator implementing a callback.
        ///
81 82
        /// @param status a @c DNSClient::Status enum representing status code
        /// of DNSClient operation.
83
        virtual void operator()(DNSClient::Status status) = 0;
84 85 86 87
    };

    /// @brief Constructor.
    ///
Andrei Pavel's avatar
Andrei Pavel committed
88
    /// @param response_placeholder Message object pointer which will be updated
89
    /// with dynamically allocated object holding the DNS server's response.
90 91 92
    /// @param callback Pointer to an object implementing @c DNSClient::Callback
    /// class. This object will be called when DNS message exchange completes or
    /// if an error occurs. NULL value disables callback invocation.
93 94 95 96
    /// @param proto caller's preference regarding Transport layer protocol to
    /// be used by DNS Client to communicate with a server.
    DNSClient(D2UpdateMessagePtr& response_placeholder, Callback* callback,
              const Protocol proto = UDP);
97 98

    /// @brief Virtual destructor, does nothing.
99
    ~DNSClient();
100 101 102 103

    ///
    /// @name Copy constructor and assignment operator
    ///
104 105 106 107 108
    /// Copy constructor and assignment operator are private because there are
    /// no use cases when @DNSClient instance will need to be copied. Also, it
    /// is desired to avoid copying @DNSClient::impl_ pointer and external
    /// callbacks.
    ///
109 110 111 112 113 114 115
    //@{
private:
    DNSClient(const DNSClient& source);
    DNSClient& operator=(const DNSClient& source);
    //@}

public:
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137

    /// @brief Returns maximal allowed timeout value accepted by
    /// @c DNSClient::doUpdate.
    ///
    /// @return maximal allowed timeout value accepted by @c DNSClient::doUpdate
    static unsigned int getMaxTimeout();

    /// @brief Start asynchronous DNS Update with TSIG.
    ///
    /// This function starts asynchronous DNS Update and returns. The DNS Update
    /// will be executed by the specified IO service. Once the message exchange
    /// with a DNS server is complete, timeout occurs or IO operation is
    /// interrupted, the caller-supplied callback function will be invoked.
    ///
    /// An address and port of the DNS server is specified through the function
    /// arguments so as the same instance of the @c DNSClient can be used to
    /// initiate multiple message exchanges.
    ///
    /// @param io_service IO service to be used to run the message exchange.
    /// @param ns_addr DNS server address.
    /// @param ns_port DNS server port.
    /// @param update A DNS Update message to be sent to the server.
138 139
    /// @param wait A timeout (in milliseconds) for the response. If a response
    /// is not received within the timeout, exchange is interrupted. This value
140
    /// must not exceed maximal value for 'int' data type.
141 142 143
    /// @param tsig_key A pointer to an @c isc::dns::TSIGKey object that will
    /// (if not null) be used to sign the DNS Update message and verify the
    /// response.
144 145 146 147 148
    void doUpdate(asiolink::IOService& io_service,
                  const asiolink::IOAddress& ns_addr,
                  const uint16_t ns_port,
                  D2UpdateMessage& update,
                  const unsigned int wait,
149
                  const dns::TSIGKeyPtr& tsig_key = dns::TSIGKeyPtr());
150 151

private:
152
    DNSClientImpl* impl_;  ///< Pointer to DNSClient implementation.
153 154 155 156 157 158
};

} // namespace d2
} // namespace isc

#endif // DNS_CLIENT_H