LCOV - code coverage report
Current view: top level - http_proto - parser.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 2 6 33.3 %
Date: 2023-02-21 17:23:31 Functions: 1 3 33.3 %

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

Generated by: LCOV version 1.15