tcpdns.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright (C) 2010 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 __TCPDNS_H
  15. #define __TCPDNS_H 1
  16. #include <config.h>
  17. #include <asio.hpp>
  18. #include <boost/shared_array.hpp>
  19. #include <boost/shared_ptr.hpp>
  20. #include <dns/buffer.h>
  21. #include <dns/message.h>
  22. #include <asiolink/asiolink.h>
  23. #include <asiolink/internal/coroutine.h>
  24. // This file contains TCP-specific implementations of generic classes
  25. // defined in asiolink.h. It is *not* intended to be part of the public
  26. // API.
  27. namespace asiolink {
  28. /// \brief The \c TCPEndpoint class is a concrete derived class of
  29. /// \c IOEndpoint that represents an endpoint of a TCP connection.
  30. ///
  31. /// In the current implementation, an object of this class is always
  32. /// instantiated within the wrapper routines. Applications are expected to
  33. /// get access to the object via the abstract base class, \c IOEndpoint.
  34. /// This design may be changed when we generalize the wrapper interface.
  35. ///
  36. /// Note: this implementation is optimized for the case where this object
  37. /// is created from an ASIO endpoint object in a receiving code path
  38. /// by avoiding to make a copy of the base endpoint. For TCP it may not be
  39. /// a big deal, but when we receive UDP packets at a high rate, the copy
  40. /// overhead might be significant.
  41. class TCPEndpoint : public IOEndpoint {
  42. public:
  43. ///
  44. /// \name Constructors and Destructor
  45. ///
  46. //@{
  47. /// \brief Constructor from a pair of address and port.
  48. ///
  49. /// \param address The IP address of the endpoint.
  50. /// \param port The TCP port number of the endpoint.
  51. TCPEndpoint(const IOAddress& address, const unsigned short port) :
  52. asio_endpoint_placeholder_(
  53. new asio::ip::tcp::endpoint(
  54. asio::ip::address::from_string(address.toText()), port)),
  55. asio_endpoint_(*asio_endpoint_placeholder_)
  56. {}
  57. /// \brief Constructor from an ASIO TCP endpoint.
  58. ///
  59. /// This constructor is designed to be an efficient wrapper for the
  60. /// corresponding ASIO class, \c tcp::endpoint.
  61. ///
  62. /// \param asio_endpoint The ASIO representation of the TCP endpoint.
  63. TCPEndpoint(const asio::ip::tcp::endpoint& asio_endpoint) :
  64. asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
  65. {}
  66. /// \brief The destructor.
  67. ~TCPEndpoint() { delete asio_endpoint_placeholder_; }
  68. //@}
  69. IOAddress getAddress() const {
  70. return (asio_endpoint_.address());
  71. }
  72. uint16_t getPort() const {
  73. return (asio_endpoint_.port());
  74. }
  75. short getProtocol() const {
  76. return (asio_endpoint_.protocol().protocol());
  77. }
  78. short getFamily() const {
  79. return (asio_endpoint_.protocol().family());
  80. }
  81. // This is not part of the exosed IOEndpoint API but allows
  82. // direct access to the ASIO implementation of the endpoint
  83. const asio::ip::tcp::endpoint& getASIOEndpoint() const {
  84. return (asio_endpoint_);
  85. }
  86. private:
  87. const asio::ip::tcp::endpoint* asio_endpoint_placeholder_;
  88. const asio::ip::tcp::endpoint& asio_endpoint_;
  89. };
  90. /// \brief The \c TCPSocket class is a concrete derived class of
  91. /// \c IOSocket that represents a TCP socket.
  92. ///
  93. /// In the current implementation, an object of this class is always
  94. /// instantiated within the wrapper routines. Applications are expected to
  95. /// get access to the object via the abstract base class, \c IOSocket.
  96. /// This design may be changed when we generalize the wrapper interface.
  97. class TCPSocket : public IOSocket {
  98. private:
  99. TCPSocket(const TCPSocket& source);
  100. TCPSocket& operator=(const TCPSocket& source);
  101. public:
  102. /// \brief Constructor from an ASIO TCP socket.
  103. ///
  104. /// \param socket The ASIO representation of the TCP socket.
  105. TCPSocket(asio::ip::tcp::socket& socket) : socket_(socket) {}
  106. int getNative() const { return (socket_.native()); }
  107. int getProtocol() const { return (IPPROTO_TCP); }
  108. private:
  109. asio::ip::tcp::socket& socket_;
  110. };
  111. /// \brief A TCP-specific \c DNSServer object.
  112. ///
  113. /// This class inherits from both \c DNSServer and from \c coroutine,
  114. /// defined in coroutine.h.
  115. class TCPServer : public virtual DNSServer, public virtual coroutine {
  116. public:
  117. explicit TCPServer(asio::io_service& io_service,
  118. const asio::ip::address& addr, const uint16_t port,
  119. const SimpleCallback* checkin = NULL,
  120. const DNSLookup* lookup = NULL,
  121. const DNSAnswer* answer = NULL);
  122. void operator()(asio::error_code ec = asio::error_code(),
  123. size_t length = 0);
  124. void asyncLookup();
  125. void resume(const bool done);
  126. bool hasAnswer() { return (done_); }
  127. int value() { return (get_value()); }
  128. DNSServer* clone() {
  129. TCPServer* s = new TCPServer(*this);
  130. return (s);
  131. }
  132. private:
  133. enum { MAX_LENGTH = 65535 };
  134. static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
  135. // The ASIO service object
  136. asio::io_service& io_;
  137. // Class member variables which are dynamic, and changes to which
  138. // need to accessible from both sides of a coroutine fork or from
  139. // outside of the coroutine (i.e., from an asynchronous I/O call),
  140. // should be declared here as pointers and allocated in the
  141. // constructor or in the coroutine. This allows state information
  142. // to persist when an individual copy of the coroutine falls out
  143. // scope while waiting for an event, *so long as* there is another
  144. // object that is referencing the same data. As a side-benefit, using
  145. // pointers also reduces copy overhead for coroutine objects.
  146. //
  147. // Note: Currently these objects are allocated by "new" in the
  148. // constructor, or in the function operator while processing a query.
  149. // Repeated allocations from the heap for every incoming query is
  150. // clearly a performance issue; this must be optimized in the future.
  151. // The plan is to have a structure pre-allocate several "server state"
  152. // objects which can be pulled off a free list and placed on an in-use
  153. // list whenever a query comes in. This will serve the dual purpose
  154. // of improving performance and guaranteeing that state information
  155. // will *not* be destroyed when any one instance of the coroutine
  156. // falls out of scope while waiting for an event.
  157. //
  158. // An ASIO acceptor object to handle new connections. Created in
  159. // the constructor.
  160. boost::shared_ptr<asio::ip::tcp::acceptor> acceptor_;
  161. // Socket used to for listen for queries. Created in the
  162. // constructor and stored in a shared_ptr because socket objects
  163. // are not copyable.
  164. boost::shared_ptr<asio::ip::tcp::socket> socket_;
  165. // The buffer into which the response is written
  166. boost::shared_ptr<isc::dns::OutputBuffer> respbuf_;
  167. // \c IOMessage and \c Message objects to be passed to the
  168. // DNS lookup and answer providers
  169. boost::shared_ptr<asiolink::IOMessage> io_message_;
  170. isc::dns::MessagePtr query_message_;
  171. isc::dns::MessagePtr answer_message_;
  172. // The buffer into which the query packet is written
  173. boost::shared_array<char>data_;
  174. // State information that is entirely internal to a given instance
  175. // of the coroutine can be declared here.
  176. size_t bytes_;
  177. bool done_;
  178. // Callback functions provided by the caller
  179. const SimpleCallback* checkin_callback_;
  180. const DNSLookup* lookup_callback_;
  181. const DNSAnswer* answer_callback_;
  182. boost::shared_ptr<IOEndpoint> peer_;
  183. boost::shared_ptr<IOSocket> iosock_;
  184. };
  185. }
  186. #endif // __TCPDNS_H
  187. // Local Variables:
  188. // mode: c++
  189. // End: