LCOV - code coverage report
Current view: top level - boost/http_proto/parser.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 11 11
Test Date: 2024-06-18 18:03:13 Functions: 100.0 % 4 4

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

Generated by: LCOV version 2.1