io_asio_socket.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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_ASIO_SOCKET_H
  15. #define __IO_ASIO_SOCKET_H 1
  16. // IMPORTANT NOTE: only very few ASIO headers files can be included in
  17. // this file. In particular, asio.hpp should never be included here.
  18. // See the description of the namespace below.
  19. #include <unistd.h> // for some network system calls
  20. #include <functional>
  21. #include <string>
  22. #include <exceptions/exceptions.h>
  23. #include <coroutine.h>
  24. #include <util/buffer.h>
  25. #include <asiolink/io_error.h>
  26. #include <asiolink/io_socket.h>
  27. namespace isc {
  28. namespace asiolink {
  29. /// \brief Socket not open
  30. ///
  31. /// Thrown on an attempt to do read/write to a socket that is not open.
  32. class SocketNotOpen : public IOError {
  33. public:
  34. SocketNotOpen(const char* file, size_t line, const char* what) :
  35. IOError(file, line, what) {}
  36. };
  37. /// \brief Error setting socket options
  38. ///
  39. /// Thrown if attempt to change socket options fails.
  40. class SocketSetError : public IOError {
  41. public:
  42. SocketSetError(const char* file, size_t line, const char* what) :
  43. IOError(file, line, what) {}
  44. };
  45. /// \brief Buffer overflow
  46. ///
  47. /// Thrown if an attempt is made to receive into an area beyond the end of
  48. /// the receive data buffer.
  49. class BufferOverflow : public IOError {
  50. public:
  51. BufferOverflow(const char* file, size_t line, const char* what) :
  52. IOError(file, line, what) {}
  53. };
  54. /// Forward declaration of an IOEndpoint
  55. class IOEndpoint;
  56. /// \brief I/O Socket with asynchronous operations
  57. ///
  58. /// This class is a wrapper for the ASIO socket classes such as
  59. /// \c ip::tcp::socket and \c ip::udp::socket.
  60. ///
  61. /// This is the basic IOSocket with additional operations - open, send, receive
  62. /// and close. Depending on how the asiolink code develops, it may be a
  63. /// temporary class: its main use is to add the template parameter needed for
  64. /// the derived classes UDPSocket and TCPSocket but without changing the
  65. /// signature of the more basic IOSocket class.
  66. ///
  67. /// We may revisit this decision when we generalize the wrapper and more
  68. /// modules use it. Also, at that point we may define a separate (visible)
  69. /// derived class for testing purposes rather than providing factory methods
  70. /// (i.e., getDummy variants below).
  71. ///
  72. /// \param C Template parameter identifying type of the callback object.
  73. template <typename C>
  74. class IOAsioSocket : public IOSocket {
  75. ///
  76. /// \name Constructors and Destructor
  77. ///
  78. /// Note: The copy constructor and the assignment operator are
  79. /// intentionally defined as private, making this class non-copyable.
  80. //@{
  81. private:
  82. IOAsioSocket(const IOAsioSocket<C>& source);
  83. IOAsioSocket& operator=(const IOAsioSocket<C>& source);
  84. protected:
  85. /// \brief The default constructor.
  86. ///
  87. /// This is intentionally defined as \c protected as this base class
  88. /// should never be instantiated (except as part of a derived class).
  89. IOAsioSocket() {}
  90. public:
  91. /// The destructor.
  92. virtual ~IOAsioSocket() {}
  93. //@}
  94. /// \brief Return the "native" representation of the socket.
  95. ///
  96. /// In practice, this is the file descriptor of the socket for UNIX-like
  97. /// systems so the current implementation simply uses \c int as the type of
  98. /// the return value. We may have to need revisit this decision later.
  99. ///
  100. /// In general, the application should avoid using this method; it
  101. /// essentially discloses an implementation specific "handle" that can
  102. /// change the internal state of the socket (consider what would happen if
  103. /// the application closes it, for example). But we sometimes need to
  104. /// perform very low-level operations that requires the native
  105. /// representation. Passing the file descriptor to a different process is
  106. /// one example. This method is provided as a necessary evil for such
  107. /// limited purposes.
  108. ///
  109. /// This method never throws an exception.
  110. ///
  111. /// \return The native representation of the socket. This is the socket
  112. /// file descriptor for UNIX-like systems.
  113. virtual int getNative() const = 0;
  114. /// \brief Return the transport protocol of the socket.
  115. ///
  116. /// Currently, it returns \c IPPROTO_UDP for UDP sockets, and
  117. /// \c IPPROTO_TCP for TCP sockets.
  118. ///
  119. /// This method never throws an exception.
  120. ///
  121. /// \return \c IPPROTO_UDP for UDP sockets, \c IPPROTO_TCP for TCP sockets
  122. virtual int getProtocol() const = 0;
  123. /// \brief Is Open() synchronous?
  124. ///
  125. /// On a TCP socket, an "open" operation is a call to the socket's "open()"
  126. /// method followed by a connection to the remote system: it is an
  127. /// asynchronous operation. On a UDP socket, it is just a call to "open()"
  128. /// and completes synchronously.
  129. ///
  130. /// For TCP, signalling of the completion of the operation is done by
  131. /// by calling the callback function in the normal way. This could be done
  132. /// for UDP (by posting en event on the event queue); however, that will
  133. /// incur additional overhead in the most common case. So we give the
  134. /// caller the choice for calling this open() method synchronously or
  135. /// asynchronously.
  136. ///
  137. /// Owing to the way that the stackless coroutines are implemented, we need
  138. /// to know _before_ executing the "open" function whether or not it is
  139. /// asynchronous. So this method is called to provide that information.
  140. ///
  141. /// (The reason there is a need to know is because the call to open() passes
  142. /// in the state of the coroutine at the time the call is made. On an
  143. /// asynchronous I/O, we need to set the state to point to the statement
  144. /// after the call to open() _before_ we pass the corouine to the open()
  145. /// call. Unfortunately, the macros that set the state of the coroutine
  146. /// also yield control - which we don't want to do if the open is
  147. /// synchronous. Hence we need to know before we make the call to open()
  148. /// whether that call will complete asynchronously.)
  149. virtual bool isOpenSynchronous() const = 0;
  150. /// \brief Open AsioSocket
  151. ///
  152. /// Opens the socket for asynchronous I/O. The open will complete
  153. /// synchronously on UCP or asynchronously on TCP (in which case a callback
  154. /// will be queued).
  155. ///
  156. /// \param endpoint Pointer to the endpoint object. This is ignored for
  157. /// a UDP socket (the target is specified in the send call), but
  158. /// should be of type TCPEndpoint for a TCP connection.
  159. /// \param callback I/O Completion callback, called when the operation has
  160. /// completed, but only if the operation was asynchronous. (It is
  161. /// ignored on a UDP socket.)
  162. virtual void open(const IOEndpoint* endpoint, C& callback) = 0;
  163. /// \brief Send Asynchronously
  164. ///
  165. /// This corresponds to async_send_to() for UDP sockets and async_send()
  166. /// for TCP. In both cases an endpoint argument is supplied indicating the
  167. /// target of the send - this is ignored for TCP.
  168. ///
  169. /// \param data Data to send
  170. /// \param length Length of data to send
  171. /// \param endpoint Target of the send
  172. /// \param callback Callback object.
  173. virtual void asyncSend(const void* data, size_t length,
  174. const IOEndpoint* endpoint, C& callback) = 0;
  175. /// \brief Receive Asynchronously
  176. ///
  177. /// This corresponds to async_receive_from() for UDP sockets and
  178. /// async_receive() for TCP. In both cases, an endpoint argument is
  179. /// supplied to receive the source of the communication. For TCP it will
  180. /// be filled in with details of the connection.
  181. ///
  182. /// \param data Buffer to receive incoming message
  183. /// \param length Length of the data buffer
  184. /// \param offset Offset into buffer where data is to be put. Although the
  185. /// offset could be implied by adjusting "data" and "length"
  186. /// appropriately, using this argument allows data to be specified as
  187. /// "const void*" - the overhead of converting it to a pointer to a
  188. /// set of bytes is hidden away here.
  189. /// \param endpoint Source of the communication
  190. /// \param callback Callback object
  191. virtual void asyncReceive(void* data, size_t length, size_t offset,
  192. IOEndpoint* endpoint, C& callback) = 0;
  193. /// \brief Processes received data
  194. ///
  195. /// In the IOFetch code, data is received into a staging buffer before being
  196. /// copied into the target buffer. (This is because (a) we don't know how
  197. /// much data we will be receiving, so don't know how to size the output
  198. /// buffer and (b) TCP data is preceded by a two-byte count field that needs
  199. /// to be discarded before being returned to the user.)
  200. ///
  201. /// An additional consideration is that TCP data is not received in one
  202. /// I/O - it may take a number of I/Os - each receiving any non-zero number
  203. /// of bytes - to read the entire message.
  204. ///
  205. /// So the IOFetch code has to loop until it determines that all the data
  206. /// has been read. This is where this method comes in. It has several
  207. /// functions:
  208. ///
  209. /// - It checks if the received data is complete.
  210. /// - If data is not complete, decides if the next set of data is to go into
  211. /// the start of the staging buffer or at some offset into it. (This
  212. /// simplifies the case we could have in a TCP receive where the two-byte
  213. /// count field is received in one-byte chunks: we put off interpreting
  214. /// the count until we have all of it. The alternative - copying the
  215. /// data to the output buffer and interpreting the count from there -
  216. /// would require moving the data in the output buffer by two bytes before
  217. /// returning it to the caller.)
  218. /// - Copies data from the staging buffer into the output buffer.
  219. ///
  220. /// This functionality mainly applies to TCP receives. For UDP, all the
  221. /// data is received in one I/O, so this just copies the data into the
  222. /// output buffer.
  223. ///
  224. /// \param staging Pointer to the start of the staging buffer.
  225. /// \param length Amount of data in the staging buffer.
  226. /// \param cumulative Amount of data received before the staging buffer is
  227. /// processed (this includes the TCP count field if appropriate).
  228. /// The value should be set to zero before the receive loop is
  229. /// entered, and it will be updated by this method as required.
  230. /// \param offset Offset into the staging buffer where the next read should
  231. /// put the received data. It should be set to zero before the first
  232. /// call and may be updated by this method.
  233. /// \param expected Expected amount of data to be received. This is
  234. /// really the TCP count field and is set to that value when enough
  235. /// of a TCP message is received. It should be initialized to -1
  236. /// before the first read is executed.
  237. /// \param outbuff Output buffer. Data in the staging buffer may be copied
  238. /// to this output buffer in the call.
  239. ///
  240. /// \return true if the receive is complete, false if another receive is
  241. /// needed. This is always true for UDP, but for TCP involves
  242. /// checking the amount of data received so far against the amount
  243. /// expected (as indicated by the two-byte count field). If this
  244. /// method returns false, another read should be queued and data
  245. /// should be read into the staging buffer at offset given by the
  246. /// "offset" parameter.
  247. virtual bool processReceivedData(const void* staging, size_t length,
  248. size_t& cumulative, size_t& offset,
  249. size_t& expected,
  250. isc::util::OutputBufferPtr& outbuff) = 0;
  251. /// \brief Cancel I/O On AsioSocket
  252. virtual void cancel() = 0;
  253. /// \brief Close socket
  254. virtual void close() = 0;
  255. };
  256. #include "io_socket.h"
  257. /// \brief The \c DummyAsioSocket class is a concrete derived class of
  258. /// \c IOAsioSocket that is not associated with any real socket.
  259. ///
  260. /// This main purpose of this class is tests, where it may be desirable to
  261. /// instantiate an \c IOAsioSocket object without involving system resource
  262. /// allocation such as real network sockets.
  263. ///
  264. /// \param C Template parameter identifying type of the callback object.
  265. template <typename C>
  266. class DummyAsioSocket : public IOAsioSocket<C> {
  267. private:
  268. DummyAsioSocket(const DummyAsioSocket<C>& source);
  269. DummyAsioSocket& operator=(const DummyAsioSocket<C>& source);
  270. public:
  271. /// \brief Constructor from the protocol number.
  272. ///
  273. /// The protocol must validly identify a standard network protocol.
  274. /// For example, to specify TCP \c protocol must be \c IPPROTO_TCP.
  275. ///
  276. /// \param protocol The network protocol number for the socket.
  277. DummyAsioSocket(const int protocol) : protocol_(protocol) {}
  278. /// \brief A dummy derived method of \c IOAsioSocket::getNative().
  279. ///
  280. /// \return Always returns -1 as the object is not associated with a real
  281. /// (native) socket.
  282. virtual int getNative() const { return (-1); }
  283. /// \brief A dummy derived method of \c IOAsioSocket::getProtocol().
  284. ///
  285. /// \return Protocol socket was created with
  286. virtual int getProtocol() const { return (protocol_); }
  287. /// \brief Is socket opening synchronous?
  288. ///
  289. /// \return true - it is for this class.
  290. bool isOpenSynchronous() const {
  291. return true;
  292. }
  293. /// \brief Open AsioSocket
  294. ///
  295. /// A call that is a no-op on UDP sockets, this opens a connection to the
  296. /// system identified by the given endpoint.
  297. /// The endpoint and callback are unused.
  298. ///
  299. /// \return false indicating that the operation completed synchronously.
  300. virtual bool open(const IOEndpoint*, C&) {
  301. return (false);
  302. }
  303. /// \brief Send Asynchronously
  304. ///
  305. /// Must be supplied as it is abstract in the base class.
  306. /// This is unused.
  307. virtual void asyncSend(const void*, size_t, const IOEndpoint*, C&) {
  308. }
  309. /// \brief Receive Asynchronously
  310. ///
  311. /// Must be supplied as it is abstract in the base class.
  312. /// The parameters are unused.
  313. virtual void asyncReceive(void* data, size_t, size_t, IOEndpoint*, C&) {
  314. }
  315. /// \brief Checks if the data received is complete.
  316. ///
  317. /// \param staging Unused
  318. /// \param length Unused
  319. /// \param cumulative Unused
  320. /// \param offset Unused.
  321. /// \param expected Unused.
  322. /// \param outbuff Unused.
  323. ///
  324. /// \return Always true
  325. virtual bool receiveComplete(const void* staging, size_t length,
  326. size_t& cumulative, size_t& offset,
  327. size_t& expected,
  328. isc::util::OutputBufferPtr& outbuff)
  329. {
  330. return (true);
  331. }
  332. /// \brief Cancel I/O On AsioSocket
  333. ///
  334. /// Must be supplied as it is abstract in the base class.
  335. virtual void cancel() {
  336. }
  337. /// \brief Close socket
  338. ///
  339. /// Must be supplied as it is abstract in the base class.
  340. virtual void close() {
  341. }
  342. private:
  343. const int protocol_;
  344. };
  345. } // namespace asiolink
  346. } // namespace isc
  347. #endif // __IO_ASIO_SOCKET_H