LCOV - code coverage report
Current view: top level - http_proto - parser.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 4 8 50.0 %
Date: 2023-02-27 20:43:06 Functions: 2 4 50.0 %

          Line data    Source code
       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           0 :     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           0 :     stream(
     364             :         parser& pr) noexcept
     365           0 :         : pr_(&pr)
     366             :     {
     367           0 :     }
     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

Generated by: LCOV version 1.15