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

Generated by: LCOV version 1.15