LCOV - code coverage report
Current view: top level - http_proto - parser.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 8 9 88.9 %
Date: 2023-02-10 23:49:12 Functions: 5 6 83.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/string_view.hpp>
      16             : #include <boost/http_proto/detail/header.hpp>
      17             : #include <boost/http_proto/detail/workspace.hpp>
      18             : #include <boost/buffers/circular_buffer.hpp>
      19             : #include <boost/buffers/flat_buffer.hpp>
      20             : #include <boost/buffers/mutable_buffer_pair.hpp>
      21             : #include <boost/buffers/sink.hpp>
      22             : #include <boost/url/grammar/error.hpp>
      23             : #include <cstddef>
      24             : #include <cstdint>
      25             : #include <memory>
      26             : #include <utility>
      27             : 
      28             : namespace boost {
      29             : namespace http_proto {
      30             : 
      31             : #ifndef BOOST_HTTP_PROTO_DOCS
      32             : enum class version : char;
      33             : class request_parser;
      34             : class response_parser;
      35             : struct brotli_decoder_t;
      36             : struct brotli_encoder_t;
      37             : struct deflate_decoder_t;
      38             : struct deflate_encoder_t;
      39             : struct gzip_decoder_t;
      40             : struct gzip_encoder_t;
      41             : namespace detail {
      42             : struct codec;
      43             : }
      44             : #endif
      45             : 
      46             : /** A parser for HTTP/1 messages.
      47             : 
      48             :     The parser is strict. Any malformed
      49             :     inputs according to the documented
      50             :     HTTP ABNFs is treated as an
      51             :     unrecoverable error.
      52             : */
      53             : class BOOST_SYMBOL_VISIBLE
      54           0 :     parser
      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             :         /** Largest allowed size for the headers.
      66             : 
      67             :             This determines an upper bound on the
      68             :             allowed size of the start-line plus
      69             :             all of the individual fields in the
      70             :             headers. This counts all delimiters
      71             :             including trailing CRLFs.
      72             :         */
      73             :         std::size_t headers_limit = 16 * 1024;
      74             : 
      75             :         /** Largest allowed size for the start-line.
      76             : 
      77             :             This determines an upper bound on the
      78             :             allowed size for the request-line of
      79             :             an HTTP request or the status-line of
      80             :             an HTTP response.
      81             :         */
      82             :         std::size_t start_line_limit = 4096;
      83             : 
      84             :         /** Largest size for one field.
      85             : 
      86             :             This determines an upper bound on the
      87             :             allowed size for any single header
      88             :             in an HTTP message. This counts
      89             :             the field name, field value, and
      90             :             delimiters including a trailing CRLF.
      91             :         */
      92             :         std::size_t field_size_limit = 4096;
      93             : 
      94             :         /** Largest allowed number of fields.
      95             : 
      96             :             This determines an upper bound on the
      97             :             largest number of individual header
      98             :             fields that may appear in an HTTP
      99             :             message.
     100             :         */
     101             :         std::size_t fields_limit = 100;
     102             : 
     103             :         /** Largest allowed size for a content body.
     104             : 
     105             :             The size of the body is measured
     106             :             after removing any transfer encodings,
     107             :             including a chunked encoding.
     108             :         */
     109             :         std::uint64_t body_limit = 64 * 1024;
     110             :     };
     111             : 
     112             :     using mutable_buffers_type =
     113             :         buffers::mutable_buffer_pair;
     114             : 
     115             : private:
     116             :     BOOST_HTTP_PROTO_DECL parser(
     117             :         detail::kind, config_base const&);
     118             :     BOOST_HTTP_PROTO_DECL void construct(
     119             :         std::size_t extra_buffer_size);
     120             : public:
     121             : 
     122             :     //--------------------------------------------
     123             :     //
     124             :     // Special Members
     125             :     //
     126             :     //--------------------------------------------
     127             : 
     128             :     /** Destructor
     129             :     */
     130             :     BOOST_HTTP_PROTO_DECL
     131             :     ~parser();
     132             : 
     133             :     /** Constructor
     134             :     */
     135             :     BOOST_HTTP_PROTO_DECL
     136             :     parser(parser&&) noexcept;
     137             : 
     138             :     //--------------------------------------------
     139             :     //
     140             :     // Observers
     141             :     //
     142             :     //--------------------------------------------
     143             : 
     144             : #if 0
     145             :     /** Return true if any input was committed.
     146             :     */
     147             :     bool
     148             :     got_some() const noexcept
     149             :     {
     150             :         return st_ != state::need_start;
     151             :     }
     152             : #endif
     153             : 
     154             :     /** Return true if the complete header was parsed.
     155             :     */
     156             :     bool
     157          34 :     got_header() const noexcept
     158             :     {
     159          34 :         return st_ > state::headers;
     160             :     }
     161             : 
     162             :     /** Returns `true` if a complete message has been parsed.
     163             : 
     164             :         Calling @ref reset prepares the parser
     165             :         to process the next message in the stream.
     166             : 
     167             :     */
     168             :     bool
     169             :     is_complete() const noexcept
     170             :     {
     171             :         return st_ == state::complete;
     172             :     }
     173             : 
     174             :     BOOST_HTTP_PROTO_DECL
     175             :     string_view
     176             :     body() const noexcept;
     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             :         error_code& ec);
     221             : 
     222             :     /** Attach a body
     223             :     */
     224             :     template<
     225             :         class Sink
     226             : #ifndef BOOST_HTTP_PROTO_DOCS
     227             :         ,class = typename
     228             :             std::enable_if<
     229             :                 buffers::is_sink<Sink
     230             :                     >::value>::type
     231             : #endif
     232             :     >
     233             :     auto
     234             :     set_body(Sink&& sink) ->
     235             :         typename std::decay<
     236             :             Sink>::type;
     237             : 
     238             :     //--------------------------------------------
     239             : 
     240             :     /** Return any leftover data
     241             : 
     242             :         This is used to forward unconsumed data
     243             :         that could lie past the last message.
     244             :         For example on a CONNECT request there
     245             :         could be additional protocol-dependent
     246             :         data that we want to retrieve.
     247             :     */
     248             :     BOOST_HTTP_PROTO_DECL
     249             :     string_view
     250             :     release_buffered_data() noexcept;
     251             : 
     252             : private:
     253         745 :     void apply_params() noexcept
     254             :     {
     255         745 :     }
     256             : 
     257             :     void apply_param(...) = delete;
     258             : 
     259             :     template<class P0, class... Pn>
     260             :     void
     261           4 :     apply_params(P0&& p0, Pn&&... pn)
     262             :     {
     263             :         // If you get an error here it means
     264             :         // you passed an unknown parameter type.
     265           4 :         apply_param(std::forward<P0>(p0));
     266             : 
     267           4 :         apply_params(std::forward<Pn>(pn)...);
     268           4 :     }
     269             : 
     270             :     BOOST_HTTP_PROTO_DECL void apply_param(config_base const&) noexcept;
     271             : 
     272             :     // in detail/impl/brotli_codec.ipp
     273             :     BOOST_HTTP_PROTO_EXT_DECL void apply_param(brotli_decoder_t const&);
     274             : 
     275             :     // in detail/impl/zlib_codec.ipp
     276             :     BOOST_HTTP_PROTO_ZLIB_DECL void apply_param(deflate_decoder_t const&);
     277             :     BOOST_HTTP_PROTO_ZLIB_DECL void apply_param(gzip_decoder_t const&);
     278             : 
     279             :     detail::header const* safe_get_header() const;
     280             :     void parse_body(error_code&);
     281             :     void parse_chunk(error_code&);
     282             : 
     283             :     friend class request_parser;
     284             :     friend class response_parser;
     285             : 
     286             :     enum
     287             :     {
     288             :         br_codec = 0,
     289             :         deflate_codec = 1,
     290             :         gzip_codec = 2
     291             :     };
     292             : 
     293             :     enum class state
     294             :     {
     295             :         // order matters
     296             :         need_start,
     297             :         headers,        // header fields
     298             :         headers_done,   // delivered headers
     299             :         body,           // reading payload
     300             :         complete,       // done
     301             :     };
     302             : 
     303             :     config_base cfg_;
     304             :     detail::header h_;
     305             :     detail::workspace ws_;
     306             :     detail::header::config cfg_impl_;
     307             : 
     308             :     std::unique_ptr<
     309             :         detail::codec> dec_[3];
     310             :     buffers::flat_buffer h_buf_;
     311             :     buffers::circular_buffer b_buf_;
     312             :     buffers::circular_buffer c_buf_;
     313             :     detail::codec* cod_;
     314             : 
     315             :     state st_;
     316             :     bool got_eof_;
     317             :     bool head_response_;
     318             : };
     319             : 
     320             : } // http_proto
     321             : } // boost
     322             : 
     323             : #include <boost/http_proto/impl/parser.hpp>
     324             : 
     325             : #endif

Generated by: LCOV version 1.15