dns_client.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef DNS_CLIENT_H
  15. #define DNS_CLIENT_H
  16. #include <d2/d2_update_message.h>
  17. #include <asiolink/io_service.h>
  18. #include <util/buffer.h>
  19. #include <asiodns/io_fetch.h>
  20. #include <dns/tsig.h>
  21. namespace isc {
  22. namespace d2 {
  23. class DNSClient;
  24. typedef boost::shared_ptr<DNSClient> DNSClientPtr;
  25. /// DNSClient class implementation.
  26. class DNSClientImpl;
  27. /// @brief The @c DNSClient class handles communication with the DNS server.
  28. ///
  29. /// Communication with the DNS server is asynchronous. Caller must provide a
  30. /// 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. /// reason. The caller-supplied callback is called by the internal callback
  33. /// operator implemented by @c DNSClient. This callback is responsible for
  34. /// initializing the @c D2UpdateMessage instance which encapsulates the response
  35. /// from the DNS. This initialization does not take place if the response from
  36. /// DNS is not received.
  37. ///
  38. /// Caller must supply a pointer to the @c D2UpdateMessage object, which will
  39. /// encapsulate DNS response, through class constructor. An exception will be
  40. /// thrown if the pointer is not initialized by the caller.
  41. ///
  42. /// @todo Ultimately, this class will support both TCP and UDP Transport.
  43. /// Currently only UDP is supported and can be specified as a preferred
  44. /// protocol. @c DNSClient constructor will throw an exception if TCP is
  45. /// specified. Once both protocols are supported, the @c DNSClient logic will
  46. /// try to obey caller's preference. However, it may use the other protocol if
  47. /// on its own discretion, when there is a legitimate reason to do so. For
  48. /// example, if communication with the server using preferred protocol fails.
  49. class DNSClient {
  50. public:
  51. /// @brief Transport layer protocol used by a DNS Client to communicate
  52. /// with a server.
  53. enum Protocol {
  54. UDP,
  55. TCP
  56. };
  57. /// @brief A status code of the DNSClient.
  58. enum Status {
  59. SUCCESS, ///< Response received and is ok.
  60. TIMEOUT, ///< No response, timeout.
  61. IO_STOPPED, ///< IO was stopped.
  62. INVALID_RESPONSE, ///< Response received but invalid.
  63. OTHER ///< Other, unclassified error.
  64. };
  65. /// @brief Callback for the @c DNSClient class.
  66. ///
  67. /// This is is abstract class which represents the external callback for the
  68. /// @c DNSClient. Caller must implement this class and supply its instance
  69. /// in the @c DNSClient constructor to get callbacks when the DNS Update
  70. /// exchange is complete (@see @c DNSClient).
  71. class Callback {
  72. public:
  73. /// @brief Virtual destructor.
  74. virtual ~Callback() { }
  75. /// @brief Function operator implementing a callback.
  76. ///
  77. /// @param status a @c DNSClient::Status enum representing status code
  78. /// of DNSClient operation.
  79. virtual void operator()(DNSClient::Status status) = 0;
  80. };
  81. /// @brief Constructor.
  82. ///
  83. /// @param response_placeholder Messge object pointer which will be updated
  84. /// with dynamically allocated object holding the DNS server's response.
  85. /// @param callback Pointer to an object implementing @c DNSClient::Callback
  86. /// class. This object will be called when DNS message exchange completes or
  87. /// if an error occurs. NULL value disables callback invocation.
  88. /// @param proto caller's preference regarding Transport layer protocol to
  89. /// be used by DNS Client to communicate with a server.
  90. DNSClient(D2UpdateMessagePtr& response_placeholder, Callback* callback,
  91. const Protocol proto = UDP);
  92. /// @brief Virtual destructor, does nothing.
  93. ~DNSClient();
  94. ///
  95. /// @name Copy constructor and assignment operator
  96. ///
  97. /// Copy constructor and assignment operator are private because there are
  98. /// no use cases when @DNSClient instance will need to be copied. Also, it
  99. /// is desired to avoid copying @DNSClient::impl_ pointer and external
  100. /// callbacks.
  101. ///
  102. //@{
  103. private:
  104. DNSClient(const DNSClient& source);
  105. DNSClient& operator=(const DNSClient& source);
  106. //@}
  107. public:
  108. /// @brief Returns maximal allowed timeout value accepted by
  109. /// @c DNSClient::doUpdate.
  110. ///
  111. /// @return maximal allowed timeout value accepted by @c DNSClient::doUpdate
  112. static unsigned int getMaxTimeout();
  113. /// @brief Start asynchronous DNS Update with TSIG.
  114. ///
  115. /// This function starts asynchronous DNS Update and returns. The DNS Update
  116. /// will be executed by the specified IO service. Once the message exchange
  117. /// with a DNS server is complete, timeout occurs or IO operation is
  118. /// interrupted, the caller-supplied callback function will be invoked.
  119. ///
  120. /// An address and port of the DNS server is specified through the function
  121. /// arguments so as the same instance of the @c DNSClient can be used to
  122. /// initiate multiple message exchanges.
  123. ///
  124. /// @param io_service IO service to be used to run the message exchange.
  125. /// @param ns_addr DNS server address.
  126. /// @param ns_port DNS server port.
  127. /// @param update A DNS Update message to be sent to the server.
  128. /// @param wait A timeout (in milliseconds) for the response. If a response
  129. /// is not received within the timeout, exchange is interrupted. This value
  130. /// must not exceed maximal value for 'int' data type.
  131. /// @param tsig_key An @c isc::dns::TSIGKey object representing TSIG
  132. /// context which will be used to render the DNS Update message.
  133. ///
  134. /// @todo Implement TSIG Support. Currently any attempt to call this
  135. /// function will result in exception.
  136. void doUpdate(asiolink::IOService& io_service,
  137. const asiolink::IOAddress& ns_addr,
  138. const uint16_t ns_port,
  139. D2UpdateMessage& update,
  140. const unsigned int wait,
  141. const dns::TSIGKey& tsig_key);
  142. /// @brief Start asynchronous DNS Update without TSIG.
  143. ///
  144. /// This function starts asynchronous DNS Update and returns. The DNS Update
  145. /// will be executed by the specified IO service. Once the message exchange
  146. /// with a DNS server is complete, timeout occurs or IO operation is
  147. /// interrupted, the caller-supplied callback function will be invoked.
  148. ///
  149. /// An address and port of the DNS server is specified through the function
  150. /// arguments so as the same instance of the @c DNSClient can be used to
  151. /// initiate multiple message exchanges.
  152. ///
  153. /// @param io_service IO service to be used to run the message exchange.
  154. /// @param ns_addr DNS server address.
  155. /// @param ns_port DNS server port.
  156. /// @param update A DNS Update message to be sent to the server.
  157. /// @param wait A timeout (in milliseconds) for the response. If a response
  158. /// is not received within the timeout, exchange is interrupted. This value
  159. /// must not exceed maximal value for 'int' data type.
  160. void doUpdate(asiolink::IOService& io_service,
  161. const asiolink::IOAddress& ns_addr,
  162. const uint16_t ns_port,
  163. D2UpdateMessage& update,
  164. const unsigned int wait);
  165. private:
  166. DNSClientImpl* impl_; ///< Pointer to DNSClient implementation.
  167. };
  168. } // namespace d2
  169. } // namespace isc
  170. #endif // DNS_CLIENT_H