GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/parser.hpp
Date: 2023-02-27 20:43:06
Exec Total Coverage
Lines: 4 7 57.1%
Functions: 2 4 50.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAlliance/http_proto
8 //
9
10 #ifndef BOOST_HTTP_PROTO_PARSER_HPP
11 #define BOOST_HTTP_PROTO_PARSER_HPP
12
13 #include <boost/http_proto/detail/config.hpp>
14 #include <boost/http_proto/error.hpp>
15 #include <boost/http_proto/header_limits.hpp>
16 #include <boost/http_proto/sink.hpp>
17 #include <boost/http_proto/detail/header.hpp>
18 #include <boost/http_proto/detail/workspace.hpp>
19 #include <boost/buffers/circular_buffer.hpp>
20 #include <boost/buffers/flat_buffer.hpp>
21 #include <boost/buffers/mutable_buffer_pair.hpp>
22 #include <boost/buffers/mutable_buffer_span.hpp>
23 #include <boost/buffers/type_traits.hpp>
24 #include <boost/url/grammar/error.hpp>
25 #include <cstddef>
26 #include <cstdint>
27 #include <memory>
28 #include <utility>
29
30 namespace boost {
31 namespace http_proto {
32
33 #ifndef BOOST_HTTP_PROTO_DOCS
34 class parser_service;
35 class filter;
36 class request_parser;
37 class response_parser;
38 class context;
39
40 #endif
41
42 /** A parser for HTTP/1 messages.
43
44 The parser is strict. Any malformed
45 inputs according to the documented
46 HTTP ABNFs is treated as an
47 unrecoverable error.
48 */
49 class BOOST_SYMBOL_VISIBLE
50 parser
51 {
52 BOOST_HTTP_PROTO_DECL
53 parser(context& ctx, detail::kind);
54
55 public:
56 /** Parser configuration settings
57
58 @see
59 @li <a href="https://stackoverflow.com/questions/686217/maximum-on-http-header-values"
60 >Maximum on HTTP header values (Stackoverflow)</a>
61 */
62 struct config_base
63 {
64 header_limits headers;
65
66 /** Largest allowed size for a content body.
67
68 The size of the body is measured
69 after removing any transfer encodings,
70 including a chunked encoding.
71 */
72 std::uint64_t body_limit = 64 * 1024;
73
74 /** True if parser can decode deflate transfer and content encodings.
75
76 The deflate decoder must already be
77 installed thusly, or else an exception
78 is thrown.
79
80 @par Install Deflate Decoder
81 @code
82 deflate_decoder_service::config cfg;
83 cfg.install( ctx );
84 @endcode
85 */
86 bool apply_deflate_decoder = false;
87
88 /** Minimum space for payload buffering.
89
90 This value controls the following
91 settings:
92
93 @li The smallest allocated size of
94 the buffers used for reading
95 and decoding the payload.
96
97 @li The lowest guaranteed size of
98 an in-place body.
99
100 @li The largest size used to reserve
101 space in dynamic buffer bodies
102 when the payload size is not
103 known ahead of time.
104
105 This cannot be zero, and this cannot
106 be greater than @ref body_limit.
107 */
108 std::size_t min_buffer = 4096;
109
110 /** Largest permissible output size in prepare.
111
112 This cannot be zero.
113 */
114 std::size_t max_prepare = std::size_t(-1);
115
116 /** Space to reserve for type-erasure.
117 */
118 std::size_t max_type_erase = 1024;
119 };
120
121 using mutable_buffers_type =
122 buffers::mutable_buffer_span;
123
124 struct stream;
125
126 //--------------------------------------------
127 //
128 // Special Members
129 //
130 //--------------------------------------------
131
132 /** Destructor.
133 */
134 BOOST_HTTP_PROTO_DECL
135 ~parser();
136
137 /** Constructor.
138 */
139 BOOST_HTTP_PROTO_DECL
140 parser(parser&&) noexcept;
141
142 //--------------------------------------------
143 //
144 // Observers
145 //
146 //--------------------------------------------
147
148 #if 0
149 /** Return true if any input was committed.
150 */
151 bool
152 got_some() const noexcept
153 {
154 return st_ != state::need_start;
155 }
156 #endif
157
158 /** Return true if the complete header was parsed.
159 */
160 bool
161 5914 got_header() const noexcept
162 {
163 5914 return st_ > state::header;
164 }
165
166 /** Returns `true` if a complete message has been parsed.
167
168 Calling @ref reset prepares the parser
169 to process the next message in the stream.
170
171 */
172 bool
173 5914 is_complete() const noexcept
174 {
175 5914 return st_ == state::complete;
176 }
177
178 //--------------------------------------------
179 //
180 // Modifiers
181 //
182 //--------------------------------------------
183
184 /** Prepare for a new stream.
185 */
186 BOOST_HTTP_PROTO_DECL
187 void
188 reset() noexcept;
189
190 private:
191 // New message on the current stream
192 BOOST_HTTP_PROTO_DECL void
193 start_impl(bool head_response);
194 public:
195
196 /** Return the input buffer
197 */
198 BOOST_HTTP_PROTO_DECL
199 mutable_buffers_type
200 prepare();
201
202 /** Commit bytes to the input buffer
203 */
204 BOOST_HTTP_PROTO_DECL
205 void
206 commit(
207 std::size_t n);
208
209 /** Indicate there will be no more input
210 */
211 BOOST_HTTP_PROTO_DECL
212 void
213 commit_eof();
214
215 /** Parse pending input data
216 */
217 BOOST_HTTP_PROTO_DECL
218 void
219 parse(
220 system::error_code& ec);
221
222 /** Attach a body
223 */
224 // VFALCO Should this function have
225 // error_code& ec and call parse?
226 template<class DynamicBuffer>
227 #ifndef BOOST_HTTP_PROTO_DOCS
228 typename std::enable_if<
229 buffers::is_dynamic_buffer<
230 DynamicBuffer>::value,
231 typename std::decay<
232 DynamicBuffer>::type
233 >::type
234 #else
235 typename std::decay<
236 DynamicBuffer>::type
237 #endif
238 set_body(DynamicBuffer&& b);
239
240 /** Attach a body
241 */
242 // VFALCO Should this function have
243 // error_code& ec and call parse?
244 template<class Sink>
245 #ifndef BOOST_HTTP_PROTO_DOCS
246 typename std::enable_if<
247 is_sink<Sink>::value,
248 typename std::decay<Sink>::type
249 >::type
250 #else
251 typename std::decay<Sink>::type
252 #endif
253 set_body(Sink&& sink);
254
255 /** Return a stream for receiving body data.
256 */
257 BOOST_HTTP_PROTO_DECL
258 stream
259 get_stream();
260
261 BOOST_HTTP_PROTO_DECL
262 core::string_view
263 in_place_body() const;
264
265 //--------------------------------------------
266
267 /** Return any leftover data
268
269 This is used to forward unconsumed data
270 that could lie past the last message.
271 For example on a CONNECT request there
272 could be additional protocol-dependent
273 data that we want to retrieve.
274 */
275 BOOST_HTTP_PROTO_DECL
276 core::string_view
277 release_buffered_data() noexcept;
278
279 private:
280 friend class request_parser;
281 friend class response_parser;
282
283 detail::header const*
284 safe_get_header() const;
285 void on_headers(system::error_code&);
286 void on_set_body();
287
288 template<class T>
289 struct any_dynamic_impl;
290 struct any_dynamic;
291 static constexpr unsigned dynamic_N_ = 8;
292
293 enum class state
294 {
295 // order matters
296 reset,
297 start,
298 header,
299 body,
300 complete,
301 };
302
303 enum class body
304 {
305 in_place,
306 dynamic,
307 sink,
308 stream
309 };
310
311 context& ctx_;
312 parser_service& svc_;
313 detail::workspace ws_;
314 detail::header h_;
315
316 buffers::flat_buffer fb_;
317 buffers::circular_buffer cb0_;
318 buffers::circular_buffer cb1_;
319 buffers::circular_buffer* body_buf_;
320 buffers::mutable_buffer_pair mbp_;
321 any_dynamic* dyn_;
322 filter* filt_;
323 sink* sink_;
324
325 state st_;
326 body body_;
327 bool got_eof_;
328 bool head_response_;
329 };
330
331 //------------------------------------------------
332
333 struct parser::stream
334 {
335 /** Constructor.
336 */
337 stream() = default;
338
339 /** Constructor.
340 */
341 stream(stream const&) = default;
342
343 /** Constructor.
344 */
345 stream& operator=
346 (stream const&) = default;
347
348 using buffers_type =
349 buffers::const_buffer_pair;
350
351 BOOST_HTTP_PROTO_DECL
352 buffers_type
353 data() const noexcept;
354
355 BOOST_HTTP_PROTO_DECL
356 void
357 consume(std::size_t n);
358
359 private:
360 friend class parser;
361
362 explicit
363 stream(
364 parser& pr) noexcept
365 : pr_(&pr)
366 {
367 }
368
369 parser* pr_ = nullptr;
370 };
371
372 //------------------------------------------------
373
374 /** Install the parser service.
375 */
376 BOOST_HTTP_PROTO_DECL
377 void
378 install_parser_service(
379 context& ctx,
380 parser::config_base const& cfg);
381
382 } // http_proto
383 } // boost
384
385 #include <boost/http_proto/impl/parser.hpp>
386
387 #endif
388