io_fetch.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 __IO_FETCH_H
  15. #define __IO_FETCH_H 1
  16. #include <config.h>
  17. #include <netinet/in.h>
  18. #include <sys/socket.h>
  19. #include <unistd.h> // for some IPC/network system calls
  20. #include <boost/shared_array.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. #include <boost/date_time/posix_time/posix_time_types.hpp>
  23. #include <asio/deadline_timer.hpp>
  24. #include <coroutine.h>
  25. #include <dns/buffer.h>
  26. #include <dns/question.h>
  27. #include <asiolink/io_asio_socket.h>
  28. #include <asiolink/io_endpoint.h>
  29. #include <asiolink/io_service.h>
  30. #include <asiolink/tcp_socket.h>
  31. #include <asiolink/tcp_endpoint.h>
  32. #include <asiolink/udp_socket.h>
  33. #include <asiolink/udp_endpoint.h>
  34. namespace asiolink {
  35. /// \brief Upstream Fetch Processing
  36. ///
  37. /// IOFetch is the class used to send upstream fetches and to handle responses.
  38. ///
  39. /// \param E Endpoint type to use.
  40. class IOFetch : public coroutine {
  41. public:
  42. /// \brief Result of Upstream Fetch
  43. ///
  44. /// Note that this applies to the status of I/Os in the fetch - a fetch
  45. /// that resulted in a packet being received from the server is a SUCCESS,
  46. /// even if the contents of the packet indicate that some error occurred.
  47. enum Result {
  48. SUCCESS = 0, ///< Success, fetch completed
  49. TIME_OUT, ///< Failure, fetch timed out
  50. STOPPED, ///< Control code, fetch has been stopped
  51. NOTSET ///< For testing, indicates value not set
  52. };
  53. // The next enum is a "trick" to allow constants to be defined in a class
  54. // declaration.
  55. /// \brief Integer Constants
  56. enum {
  57. MAX_LENGTH = 4096 ///< Maximum size of receive buffer
  58. };
  59. /// \brief I/O Fetch Callback
  60. ///
  61. /// TODO: change documentation
  62. /// Callback object for when the fetch itself has completed. Note that this
  63. /// is different to the IOCompletionCallback; that is used to signal the
  64. /// completion of an asynchronous I/O call. The IOFetch::Callback is called
  65. /// when an upstream fetch - which may have involved several asynchronous
  66. /// I/O operations - has completed.
  67. ///
  68. /// This is an abstract class.
  69. class Callback {
  70. public:
  71. /// \brief Default Constructor
  72. Callback()
  73. {}
  74. /// \brief Virtual Destructor
  75. virtual ~Callback()
  76. {}
  77. /// \brief Callback method called when the fetch completes
  78. ///
  79. /// \brief result Result of the fetch
  80. virtual void operator()(Result result) = 0;
  81. };
  82. /// \brief IOFetch Data
  83. ///
  84. /// The data for IOFetch is held in a separate struct pointed to by a
  85. /// shared_ptr object. This is because the IOFetch object will be copied
  86. /// often (it is used as a coroutine and passed as callback to many
  87. /// async_*() functions) and we want keep the same data). Organising the
  88. /// data in this way keeps copying to a minimum.
  89. struct IOFetchData {
  90. // The next two members are shared pointers to a base class because what
  91. // is actually instantiated depends on whether the fetch is over UDP or
  92. // TCP, which is not known until construction of the IOFetch. Use of
  93. // a shared pointer here is merely to ensure deletion when the data
  94. // object is deleted.
  95. boost::shared_ptr<IOAsioSocket<IOFetch> > socket;
  96. ///< Socket to use for I/O
  97. boost::shared_ptr<IOEndpoint> remote; ///< Where the fetch was sent
  98. isc::dns::Question question; ///< Question to be asked
  99. isc::dns::OutputBufferPtr msgbuf; ///< Wire buffer for question
  100. isc::dns::OutputBufferPtr buffer; ///< Received data held here
  101. boost::shared_array<char> data; ///< Temporary array for data
  102. IOFetch::Callback* callback; ///< Called on I/O Completion
  103. size_t cumulative; ///< Cumulative received amount
  104. bool stopped; ///< Have we stopped running?
  105. asio::deadline_timer timer; ///< Timer to measure timeouts
  106. int timeout; ///< Timeout in ms
  107. /// \brief Constructor
  108. ///
  109. /// Just fills in the data members of the IOFetchData structure
  110. ///
  111. /// \param protocol either IPPROTO_UDP or IPPROTO_TCP
  112. /// \param service I/O Service object to handle the asynchronous
  113. /// operations.
  114. /// \param query DNS question to send to the upstream server.
  115. /// \param address IP address of upstream server
  116. /// \param port Port to use for the query
  117. /// \param buff Output buffer into which the response (in wire format)
  118. /// is written (if a response is received).
  119. /// \param cb Callback object containing the callback to be called
  120. /// when we terminate. The caller is responsible for managing this
  121. /// object and deleting it if necessary.
  122. /// \param wait Timeout for the fetch (in ms).
  123. IOFetchData(int protocol, IOService& service,
  124. const isc::dns::Question& query, const IOAddress& address,
  125. uint16_t port, isc::dns::OutputBufferPtr& buff, Callback* cb,
  126. int wait)
  127. :
  128. socket((protocol == IPPROTO_UDP) ?
  129. static_cast<IOAsioSocket<IOFetch>*>(
  130. new UDPSocket<IOFetch>(service)) :
  131. static_cast<IOAsioSocket<IOFetch>*>(
  132. new TCPSocket<IOFetch>(service))
  133. ),
  134. remote((protocol == IPPROTO_UDP) ?
  135. static_cast<IOEndpoint*>(new UDPEndpoint(address, port)) :
  136. static_cast<IOEndpoint*>(new TCPEndpoint(address, port))
  137. ),
  138. question(query),
  139. msgbuf(new isc::dns::OutputBuffer(512)),
  140. buffer(buff),
  141. data(new char[IOFetch::MAX_LENGTH]),
  142. callback(cb),
  143. cumulative(0),
  144. stopped(false),
  145. timer(service.get_io_service()),
  146. timeout(wait)
  147. {}
  148. };
  149. /// \brief Constructor.
  150. ///
  151. /// Creates the object that will handle the upstream fetch.
  152. ///
  153. /// TODO: Need to randomise the source port
  154. ///
  155. /// \param protocol Fetch protocol, either IPPROTO_UDP or IPPROTO_TCP
  156. /// \param service I/O Service object to handle the asynchronous
  157. /// operations.
  158. /// \param question DNS question to send to the upstream server.
  159. /// \param buff Output buffer into which the response (in wire format)
  160. /// is written (if a response is received).
  161. /// \param cb Callback object containing the callback to be called
  162. /// when we terminate. The caller is responsible for managing this
  163. /// object and deleting it if necessary.
  164. /// \param address IP address of upstream server
  165. /// \param port Port to which to connect on the upstream server
  166. /// (default = 53)
  167. /// \param wait Timeout for the fetch (in ms). The default value of
  168. /// -1 indicates no timeout.
  169. IOFetch(int protocol, IOService& service,
  170. const isc::dns::Question& question, const IOAddress& address,
  171. uint16_t port, isc::dns::OutputBufferPtr& buff, Callback* cb,
  172. int wait = -1);
  173. // The default constructor and copy constructor are correct for this method.
  174. /// \brief Coroutine entry point
  175. ///
  176. /// The operator() method is the method in which the coroutine code enters
  177. /// this object when an operation has been completed.
  178. ///
  179. /// \param ec Error code, the result of the last asynchronous I/O operation.
  180. /// \param length Amount of data received on the last asynchronous read
  181. void operator()(asio::error_code ec = asio::error_code(),
  182. size_t length = 0);
  183. /// \brief Terminate query
  184. ///
  185. /// This method can be called at any point. It terminates the current
  186. /// query with the specified reason.
  187. ///
  188. /// \param reason Reason for terminating the query
  189. void stop(Result reason = STOPPED);
  190. private:
  191. boost::shared_ptr<IOFetchData> data_; ///< Private data
  192. };
  193. } // namespace asiolink
  194. #endif // __IO_FETCH_H