• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #include <boost/beast/core/buffer_traits.hpp>
11 #include <boost/beast/core/error.hpp>
12 #include <boost/beast/core/file_base.hpp>
13 #include <boost/beast/http/message.hpp>
14 #include <boost/beast/http/type_traits.hpp>
15 #include <boost/optional.hpp>
16 #include <cstdint>
17 #include <utility>
18 
19 namespace boost {
20 namespace beast {
21 namespace http {
22 
23 class BodyWriter;
24 class BodyReader;
25 
26 //[concept_Body
27 
28 struct Body
29 {
30     // The type of message::body when used
31     struct value_type;
32 
33     /// The algorithm used during parsing
34     class reader;
35 
36     /// The algorithm used during serialization
37     class writer;
38 
39     /// Returns the body's payload size
40     static
41     std::uint64_t
42     size(value_type const& body);
43 };
44 
45 static_assert(is_body<Body>::value, "");
46 
47 //]
48 
49 struct Body_BodyWriter {
50     struct value_type{};
51 //[concept_BodyWriter
52 
53 struct BodyWriter
54 {
55 public:
56     /// The type of buffer returned by `get`.
57     using const_buffers_type = net::const_buffer;
58 
59     /** Construct the writer.
60 
61         @param h The header for the message being serialized
62 
63         @param body The body being serialized
64     */
65     template<bool isRequest, class Fields>
66     BodyWriter(header<isRequest, Fields> const& h, value_type const& body);
67 
68     /** Initialize the writer.
69 
70         This is called after construction and before the first
71         call to `get`. The message is valid and complete upon
72         entry.
73 
74         @param ec Set to the error, if any occurred.
75     */
76     void
initboost::beast::http::Body_BodyWriter::BodyWriter77     init(error_code& ec)
78     {
79         // The specification requires this to indicate "no error"
80         ec = {};
81     }
82 
83     /** Returns the next buffer in the body.
84 
85         @li If the return value is `boost::none` (unseated optional) and
86             `ec` does not contain an error, this indicates the end of the
87             body, no more buffers are present.
88 
89         @li If the optional contains a value, the first element of the
90             pair represents a <em>ConstBufferSequence</em> containing one or
91             more octets of the body data. The second element indicates
92             whether or not there are additional octets of body data.
93             A value of `true` means there is more data, and that the
94             implementation will perform a subsequent call to `get`.
95             A value of `false` means there is no more body data.
96 
97         @li If `ec` contains an error code, the return value is ignored.
98 
99         @param ec Set to the error, if any occurred.
100     */
101     boost::optional<std::pair<const_buffers_type, bool>>
getboost::beast::http::Body_BodyWriter::BodyWriter102     get(error_code& ec)
103     {
104         // The specification requires this to indicate "no error"
105         ec = {};
106 
107         return boost::none; // for exposition only
108     }
109 };
110 
111 //]
112     using writer = BodyWriter;
113 };
114 
115 static_assert(is_body_writer<Body_BodyWriter>::value, "");
116 
117 struct Body_BodyReader {
118     struct value_type{};
119 //[concept_BodyReader
120 
121 struct BodyReader
122 {
123     /** Construct the reader.
124 
125         @param h The header for the message being parsed
126 
127         @param body The body to store the parsed results into
128     */
129     template<bool isRequest, class Fields>
130     BodyReader(header<isRequest, Fields>& h, value_type& body);
131 
132     /** Initialize the reader.
133 
134         This is called after construction and before the first
135         call to `put`. The message is valid and complete upon
136         entry.
137 
138         @param ec Set to the error, if any occurred.
139     */
140     void
initboost::beast::http::Body_BodyReader::BodyReader141     init(
142         boost::optional<std::uint64_t> const& content_length,
143         error_code& ec)
144     {
145         boost::ignore_unused(content_length);
146 
147         // The specification requires this to indicate "no error"
148         ec = {};
149     }
150 
151     /** Store buffers.
152 
153         This is called zero or more times with parsed body octets.
154 
155         @param buffers The constant buffer sequence to store.
156 
157         @param ec Set to the error, if any occurred.
158 
159         @return The number of bytes transferred from the input buffers.
160     */
161     template<class ConstBufferSequence>
162     std::size_t
putboost::beast::http::Body_BodyReader::BodyReader163     put(ConstBufferSequence const& buffers, error_code& ec)
164     {
165         // The specification requires this to indicate "no error"
166         ec = {};
167 
168         return buffer_bytes(buffers);
169     }
170 
171     /** Called when the body is complete.
172 
173         @param ec Set to the error, if any occurred.
174     */
175     void
finishboost::beast::http::Body_BodyReader::BodyReader176     finish(error_code& ec)
177     {
178         // The specification requires this to indicate "no error"
179         ec = {};
180     }
181 };
182 
183 //]
184     using reader = BodyReader;
185 };
186 
187 static_assert(is_body_reader<Body_BodyReader>::value, "");
188 
189 //[concept_Fields
190 
191 class Fields
192 {
193 public:
194     /// Constructed as needed when fields are serialized
195     struct writer;
196 
197 protected:
198     /** Returns the request-method string.
199 
200         @note Only called for requests.
201     */
202     string_view
203     get_method_impl() const;
204 
205     /** Returns the request-target string.
206 
207         @note Only called for requests.
208     */
209     string_view
210     get_target_impl() const;
211 
212     /** Returns the response reason-phrase string.
213 
214         @note Only called for responses.
215     */
216     string_view
217     get_reason_impl() const;
218 
219     /** Returns the chunked Transfer-Encoding setting
220     */
221     bool
222     get_chunked_impl() const;
223 
224     /** Returns the keep-alive setting
225     */
226     bool
227     get_keep_alive_impl(unsigned version) const;
228 
229     /** Returns `true` if the Content-Length field is present.
230     */
231     bool
232     has_content_length_impl() const;
233 
234     /** Set or clear the method string.
235 
236         @note Only called for requests.
237     */
238     void
239     set_method_impl(string_view s);
240 
241     /** Set or clear the target string.
242 
243         @note Only called for requests.
244     */
245     void
246     set_target_impl(string_view s);
247 
248     /** Set or clear the reason string.
249 
250         @note Only called for responses.
251     */
252     void
253     set_reason_impl(string_view s);
254 
255     /** Sets or clears the chunked Transfer-Encoding value
256     */
257     void
258     set_chunked_impl(bool value);
259 
260     /** Sets or clears the Content-Length field
261     */
262     void
263     set_content_length_impl(boost::optional<std::uint64_t>);
264 
265     /** Adjusts the Connection field
266     */
267     void
268     set_keep_alive_impl(unsigned version, bool keep_alive);
269 };
270 
271 static_assert(is_fields<Fields>::value,
272     "Fields type requirements not met");
273 
274 //]
275 
276 struct Fields_FieldsWriter {
277     using Fields = Fields_FieldsWriter;
278 //[concept_FieldsWriter
279 
280 struct FieldsWriter
281 {
282     // The type of buffers returned by `get`
283     struct const_buffers_type;
284 
285     // Constructor for requests
286     FieldsWriter(Fields const& f, unsigned version, verb method);
287 
288     // Constructor for responses
289     FieldsWriter(Fields const& f, unsigned version, unsigned status);
290 
291     // Returns the serialized header buffers
292     const_buffers_type
293     get();
294 };
295 
296 //]
297 };
298 
299 //[concept_File
300 
301 struct File
302 {
303     /** Default constructor
304 
305         There is no open file initially.
306     */
307     File();
308 
309     /** Destructor
310 
311         If the file is open it is first closed.
312     */
313     ~File();
314 
315     /// Returns `true` if the file is open
316     bool
317     is_open() const;
318 
319     /// Close the file if open
320     void
321     close(error_code& ec);
322 
323     /// Open a file at the given path with the specified mode
324     void
325     open(char const* path, file_mode mode, error_code& ec);
326 
327     /// Return the size of the open file
328     std::uint64_t
329     size(error_code& ec) const;
330 
331     /// Return the current position in the open file
332     std::uint64_t
333     pos(error_code& ec) const;
334 
335     /// Adjust the current position in the open file
336     void
337     seek(std::uint64_t offset, error_code& ec);
338 
339     /// Read from the open file
340     std::size_t
341     read(void* buffer, std::size_t n, error_code& ec) const;
342 
343     /// Write to the open file
344     std::size_t
345     write(void const* buffer, std::size_t n, error_code& ec);
346 };
347 
348 //]
349 
350 } // http
351 } // beast
352 } // boost
353