buffer_body.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_HTTP_BUFFER_BODY_HPP
  10. #define BOOST_BEAST_HTTP_BUFFER_BODY_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/buffer_traits.hpp>
  13. #include <boost/beast/http/error.hpp>
  14. #include <boost/beast/http/message.hpp>
  15. #include <boost/beast/http/type_traits.hpp>
  16. #include <boost/optional.hpp>
  17. #include <cstdint>
  18. #include <type_traits>
  19. #include <utility>
  20. namespace boost {
  21. namespace beast {
  22. namespace http {
  23. /** A <em>Body</em> using a caller provided buffer
  24. Messages using this body type may be serialized and parsed.
  25. To use this class, the caller must initialize the members
  26. of @ref buffer_body::value_type to appropriate values before
  27. each call to read or write during a stream operation.
  28. */
  29. struct buffer_body
  30. {
  31. /// The type of the body member when used in a message.
  32. struct value_type
  33. {
  34. /** A pointer to a contiguous area of memory of @ref size octets, else `nullptr`.
  35. @par When Serializing
  36. If this is `nullptr` and `more` is `true`, the error
  37. @ref error::need_buffer will be returned from @ref serializer::get
  38. Otherwise, the serializer will use the memory pointed to
  39. by `data` having `size` octets of valid storage as the
  40. next buffer representing the body.
  41. @par When Parsing
  42. If this is `nullptr`, the error @ref error::need_buffer
  43. will be returned from @ref parser::put. Otherwise, the
  44. parser will store body octets into the memory pointed to
  45. by `data` having `size` octets of valid storage. After
  46. octets are stored, the `data` and `size` members are
  47. adjusted: `data` is incremented to point to the next
  48. octet after the data written, while `size` is decremented
  49. to reflect the remaining space at the memory location
  50. pointed to by `data`.
  51. */
  52. void* data = nullptr;
  53. /** The number of octets in the buffer pointed to by @ref data.
  54. @par When Serializing
  55. If `data` is `nullptr` during serialization, this value
  56. is ignored. Otherwise, it represents the number of valid
  57. body octets pointed to by `data`.
  58. @par When Parsing
  59. The value of this field will be decremented during parsing
  60. to indicate the number of remaining free octets in the
  61. buffer pointed to by `data`. When it reaches zero, the
  62. parser will return @ref error::need_buffer, indicating to
  63. the caller that the values of `data` and `size` should be
  64. updated to point to a new memory buffer.
  65. */
  66. std::size_t size = 0;
  67. /** `true` if this is not the last buffer.
  68. @par When Serializing
  69. If this is `true` and `data` is `nullptr`, the error
  70. @ref error::need_buffer will be returned from @ref serializer::get
  71. @par When Parsing
  72. This field is not used during parsing.
  73. */
  74. bool more = true;
  75. };
  76. /** The algorithm for parsing the body
  77. Meets the requirements of <em>BodyReader</em>.
  78. */
  79. #if BOOST_BEAST_DOXYGEN
  80. using reader = __implementation_defined__;
  81. #else
  82. class reader
  83. {
  84. value_type& body_;
  85. public:
  86. template<bool isRequest, class Fields>
  87. explicit
  88. reader(header<isRequest, Fields>&, value_type& b)
  89. : body_(b)
  90. {
  91. }
  92. void
  93. init(boost::optional<std::uint64_t> const&, error_code& ec)
  94. {
  95. ec = {};
  96. }
  97. template<class ConstBufferSequence>
  98. std::size_t
  99. put(ConstBufferSequence const& buffers,
  100. error_code& ec)
  101. {
  102. if(! body_.data)
  103. {
  104. BOOST_BEAST_ASSIGN_EC(ec, error::need_buffer);
  105. return 0;
  106. }
  107. auto const bytes_transferred =
  108. net::buffer_copy(net::buffer(
  109. body_.data, body_.size), buffers);
  110. body_.data = static_cast<char*>(
  111. body_.data) + bytes_transferred;
  112. body_.size -= bytes_transferred;
  113. if(bytes_transferred == buffer_bytes(buffers))
  114. ec = {};
  115. else
  116. {
  117. BOOST_BEAST_ASSIGN_EC(ec, error::need_buffer);
  118. }
  119. return bytes_transferred;
  120. }
  121. void
  122. finish(error_code& ec)
  123. {
  124. ec = {};
  125. }
  126. };
  127. #endif
  128. /** The algorithm for serializing the body
  129. Meets the requirements of <em>BodyWriter</em>.
  130. */
  131. #if BOOST_BEAST_DOXYGEN
  132. using writer = __implementation_defined__;
  133. #else
  134. class writer
  135. {
  136. bool toggle_ = false;
  137. value_type const& body_;
  138. public:
  139. using const_buffers_type =
  140. net::const_buffer;
  141. template<bool isRequest, class Fields>
  142. explicit
  143. writer(header<isRequest, Fields> const&, value_type const& b)
  144. : body_(b)
  145. {
  146. }
  147. void
  148. init(error_code& ec)
  149. {
  150. ec = {};
  151. }
  152. boost::optional<
  153. std::pair<const_buffers_type, bool>>
  154. get(error_code& ec)
  155. {
  156. if(toggle_)
  157. {
  158. if(body_.more)
  159. {
  160. toggle_ = false;
  161. BOOST_BEAST_ASSIGN_EC(ec, error::need_buffer);
  162. }
  163. else
  164. {
  165. ec = {};
  166. }
  167. return boost::none;
  168. }
  169. if(body_.data)
  170. {
  171. ec = {};
  172. toggle_ = true;
  173. return {{const_buffers_type{
  174. body_.data, body_.size}, body_.more}};
  175. }
  176. if(body_.more)
  177. {
  178. BOOST_BEAST_ASSIGN_EC(ec, error::need_buffer);
  179. }
  180. else
  181. ec = {};
  182. return boost::none;
  183. }
  184. };
  185. #endif
  186. };
  187. #if ! BOOST_BEAST_DOXYGEN
  188. // operator<< is not supported for buffer_body
  189. template<bool isRequest, class Fields>
  190. std::ostream&
  191. operator<<(std::ostream& os, message<isRequest,
  192. buffer_body, Fields> const& msg) = delete;
  193. #endif
  194. } // http
  195. } // beast
  196. } // boost
  197. #endif