Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:31

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_HTTP_CHUNK_ENCODE_HPP
0011 #define BOOST_BEAST_HTTP_CHUNK_ENCODE_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 #include <boost/beast/core/buffers_cat.hpp>
0015 #include <boost/beast/core/string.hpp>
0016 #include <boost/beast/http/type_traits.hpp>
0017 #include <boost/beast/http/detail/chunk_encode.hpp>
0018 #include <boost/asio/buffer.hpp>
0019 #include <memory>
0020 #include <type_traits>
0021 
0022 namespace boost {
0023 namespace beast {
0024 namespace http {
0025 
0026 /** A chunked encoding crlf
0027 
0028     This implements a <em>ConstBufferSequence</em> holding the CRLF
0029     (`"\r\n"`) used as a delimiter in a @em chunk.
0030 
0031     To use this class, pass an instance of it to a
0032     stream algorithm as the buffer sequence:
0033     @code
0034         // writes "\r\n"
0035         net::write(stream, chunk_crlf{});
0036     @endcode
0037 
0038     @see https://tools.ietf.org/html/rfc7230#section-4.1
0039 */
0040 struct chunk_crlf
0041 {
0042     /// Constructor
0043     chunk_crlf() = default;
0044 
0045     //-----
0046 
0047     /// Required for <em>ConstBufferSequence</em>
0048 #if BOOST_BEAST_DOXYGEN
0049     using value_type = __implementation_defined__;
0050 #else
0051     using value_type = net::const_buffer;
0052 #endif
0053 
0054     /// Required for <em>ConstBufferSequence</em>
0055     using const_iterator = value_type const*;
0056 
0057     /// Required for <em>ConstBufferSequence</em>
0058     chunk_crlf(chunk_crlf const&) = default;
0059 
0060     /// Required for <em>ConstBufferSequence</em>
0061     const_iterator
0062     begin() const
0063     {
0064         static net::const_buffer const cb{"\r\n", 2};
0065         return &cb;
0066     }
0067 
0068     /// Required for <em>ConstBufferSequence</em>
0069     const_iterator
0070     end() const
0071     {
0072         return begin() + 1;
0073     }
0074 };
0075 
0076 //------------------------------------------------------------------------------
0077 
0078 /** A @em chunk header
0079 
0080     This implements a <em>ConstBufferSequence</em> representing the
0081     header of a @em chunk. The serialized format is as follows:
0082     @code
0083         chunk-header    = 1*HEXDIG chunk-ext CRLF       
0084         chunk-ext       = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
0085         chunk-ext-name  = token
0086         chunk-ext-val   = token / quoted-string
0087     @endcode
0088     The chunk extension is optional. After the header and
0089     chunk body have been serialized, it is the callers
0090     responsibility to also serialize the final CRLF (`"\r\n"`).
0091 
0092     This class allows the caller to emit piecewise chunk bodies,
0093     by first serializing the chunk header using this class and then
0094     serializing the chunk body in a series of one or more calls to
0095     a stream write operation.
0096 
0097     To use this class, pass an instance of it to a
0098     stream algorithm as the buffer sequence:
0099     @code
0100         // writes "400;x\r\n"
0101         net::write(stream, chunk_header{1024, "x"});
0102     @endcode
0103 
0104     @see https://tools.ietf.org/html/rfc7230#section-4.1
0105 */
0106 class chunk_header
0107 {
0108     using view_type = buffers_cat_view<
0109         detail::chunk_size,             // chunk-size
0110         net::const_buffer,   // chunk-extensions
0111         chunk_crlf>;                    // CRLF
0112 
0113     std::shared_ptr<
0114         detail::chunk_extensions> exts_;
0115     view_type view_;
0116 
0117 public:
0118     /** Constructor
0119 
0120         This constructs a buffer sequence representing a
0121         @em chunked-body size and terminating CRLF (`"\r\n"`)
0122         with no chunk extensions.
0123 
0124         @param size The size of the chunk body that follows.
0125         The value must be greater than zero.
0126 
0127         @see https://tools.ietf.org/html/rfc7230#section-4.1
0128     */
0129     explicit
0130     chunk_header(std::size_t size);
0131 
0132     /** Constructor
0133 
0134         This constructs a buffer sequence representing a
0135         @em chunked-body size and terminating CRLF (`"\r\n"`)
0136         with provided chunk extensions.
0137 
0138         @param size The size of the chunk body that follows.
0139         The value must be greater than zero.
0140 
0141         @param extensions The chunk extensions string. This
0142         string must be formatted correctly as per rfc7230,
0143         using this BNF syntax:
0144         @code
0145             chunk-ext       = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
0146             chunk-ext-name  = token
0147             chunk-ext-val   = token / quoted-string
0148         @endcode
0149         The data pointed to by this string view must remain
0150         valid for the lifetime of any operations performed on
0151         the object.
0152 
0153         @see https://tools.ietf.org/html/rfc7230#section-4.1.1
0154     */
0155     chunk_header(
0156         std::size_t size,
0157         string_view extensions);
0158 
0159     /** Constructor
0160 
0161         This constructs a buffer sequence representing a
0162         @em chunked-body size and terminating CRLF (`"\r\n"`)
0163         with provided chunk extensions.
0164         The default allocator is used to provide storage for the
0165         extensions object.
0166 
0167         @param size The size of the chunk body that follows.
0168         The value must be greater than zero.
0169 
0170         @param extensions The chunk extensions object. The expression
0171         `extensions.str()` must be valid, and the return type must
0172         be convertible to @ref string_view. This object will be copied
0173         or moved as needed to ensure that the chunk header object retains
0174         ownership of the buffers provided by the chunk extensions object.
0175 
0176         @note This function participates in overload resolution only
0177         if @b ChunkExtensions meets the requirements stated above.
0178 
0179         @see https://tools.ietf.org/html/rfc7230#section-4.1
0180     */
0181     template<class ChunkExtensions
0182 #if ! BOOST_BEAST_DOXYGEN
0183         , class = typename std::enable_if<
0184             detail::is_chunk_extensions<
0185                 ChunkExtensions>::value>::type
0186 #endif
0187     >
0188     chunk_header(
0189         std::size_t size,
0190         ChunkExtensions&& extensions);
0191 
0192     /** Constructor
0193 
0194         This constructs a buffer sequence representing a
0195         @em chunked-body size and terminating CRLF (`"\r\n"`)
0196         with provided chunk extensions.
0197         The specified allocator is used to provide storage for the
0198         extensions object.
0199 
0200         @param size The size of the chunk body that follows.
0201         The value be greater than zero.
0202 
0203         @param extensions The chunk extensions object. The expression
0204         `extensions.str()` must be valid, and the return type must
0205         be convertible to @ref string_view. This object will be copied
0206         or moved as needed to ensure that the chunk header object retains
0207         ownership of the buffers provided by the chunk extensions object.
0208 
0209         @param allocator The allocator to provide storage for the moved
0210         or copied extensions object.
0211 
0212         @note This function participates in overload resolution only
0213         if @b ChunkExtensions meets the requirements stated above.
0214 
0215         @see https://tools.ietf.org/html/rfc7230#section-4.1
0216     */
0217     template<class ChunkExtensions, class Allocator
0218 #if ! BOOST_BEAST_DOXYGEN
0219         , class = typename std::enable_if<
0220             detail::is_chunk_extensions<
0221                 ChunkExtensions>::value>::type
0222 #endif
0223     >
0224     chunk_header(
0225         std::size_t size,
0226         ChunkExtensions&& extensions,
0227         Allocator const& allocator);
0228 
0229     //-----
0230 
0231     /// Required for <em>ConstBufferSequence</em>
0232 #if BOOST_BEAST_DOXYGEN
0233     using value_type = __implementation_defined__;
0234 #else
0235     using value_type = typename view_type::value_type;
0236 #endif
0237 
0238     /// Required for <em>ConstBufferSequence</em>
0239 #if BOOST_BEAST_DOXYGEN
0240     using const_iterator = __implementation_defined__;
0241 #else
0242     using const_iterator = typename view_type::const_iterator;
0243 #endif
0244 
0245     /// Required for <em>ConstBufferSequence</em>
0246     chunk_header(chunk_header const&) = default;
0247 
0248     /// Required for <em>ConstBufferSequence</em>
0249     const_iterator
0250     begin() const
0251     {
0252         return view_.begin();
0253     }
0254 
0255     /// Required for <em>ConstBufferSequence</em>
0256     const_iterator
0257     end() const
0258     {
0259         return view_.end();
0260     }
0261 };
0262 
0263 //------------------------------------------------------------------------------
0264 
0265 /** A @em chunk
0266 
0267     This implements a <em>ConstBufferSequence</em> representing
0268     a @em chunk. The serialized format is as follows:
0269     @code
0270         chunk           = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
0271         chunk-size      = 1*HEXDIG
0272         chunk-ext       = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
0273         chunk-ext-name  = token
0274         chunk-ext-val   = token / quoted-string
0275         chunk-data      = 1*OCTET ; a sequence of chunk-size octets
0276     @endcode
0277     The chunk extension is optional. 
0278 
0279     To use this class, pass an instance of it to a
0280     stream algorithm as the buffer sequence.
0281 
0282     @see https://tools.ietf.org/html/rfc7230#section-4.1
0283 */
0284 template<class ConstBufferSequence>
0285 class chunk_body
0286 {
0287     using view_type = buffers_cat_view<
0288         detail::chunk_size,             // chunk-size
0289         net::const_buffer,   // chunk-extensions
0290         chunk_crlf,                     // CRLF
0291         ConstBufferSequence,            // chunk-body
0292         chunk_crlf>;                    // CRLF
0293 
0294     std::shared_ptr<
0295         detail::chunk_extensions> exts_;
0296     view_type view_;
0297 
0298 public:
0299     /** Constructor
0300 
0301         This constructs buffers representing a complete @em chunk
0302         with no chunk extensions and having the size and contents
0303         of the specified buffer sequence.
0304 
0305         @param buffers A buffer sequence representing the chunk
0306         body. Although the buffers object may be copied as necessary,
0307         ownership of the underlying memory blocks is retained by the
0308         caller, which must guarantee that they remain valid while this
0309         object is in use.
0310 
0311         @see https://tools.ietf.org/html/rfc7230#section-4.1
0312     */
0313     explicit
0314     chunk_body(
0315         ConstBufferSequence const& buffers);
0316 
0317     /** Constructor
0318 
0319         This constructs buffers representing a complete @em chunk
0320         with the passed chunk extensions and having the size and
0321         contents of the specified buffer sequence.
0322 
0323         @param buffers A buffer sequence representing the chunk
0324         body. Although the buffers object may be copied as necessary,
0325         ownership of the underlying memory blocks is retained by the
0326         caller, which must guarantee that they remain valid while this
0327         object is in use.
0328 
0329         @param extensions The chunk extensions string. This
0330         string must be formatted correctly as per rfc7230,
0331         using this BNF syntax:
0332         @code
0333             chunk-ext       = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
0334             chunk-ext-name  = token
0335             chunk-ext-val   = token / quoted-string
0336         @endcode
0337         The data pointed to by this string view must remain
0338         valid for the lifetime of any operations performed on
0339         the object.
0340 
0341         @see https://tools.ietf.org/html/rfc7230#section-4.1.1
0342     */
0343     chunk_body(
0344         ConstBufferSequence const& buffers,
0345         string_view extensions);
0346 
0347     /** Constructor
0348 
0349         This constructs buffers representing a complete @em chunk
0350         with the passed chunk extensions and having the size and
0351         contents of the specified buffer sequence.
0352         The default allocator is used to provide storage for the
0353         extensions object.
0354 
0355         @param buffers A buffer sequence representing the chunk
0356         body. Although the buffers object may be copied as necessary,
0357         ownership of the underlying memory blocks is retained by the
0358         caller, which must guarantee that they remain valid while this
0359         object is in use.
0360 
0361         @param extensions The chunk extensions object. The expression
0362         `extensions.str()` must be valid, and the return type must
0363         be convertible to @ref string_view. This object will be copied
0364         or moved as needed to ensure that the chunk header object retains
0365         ownership of the buffers provided by the chunk extensions object.
0366 
0367         @note This function participates in overload resolution only
0368         if @b ChunkExtensions meets the requirements stated above.
0369 
0370         @see https://tools.ietf.org/html/rfc7230#section-4.1
0371     */
0372     template<class ChunkExtensions
0373 #if ! BOOST_BEAST_DOXYGEN
0374         , class = typename std::enable_if<
0375             ! std::is_convertible<typename std::decay<
0376                 ChunkExtensions>::type, string_view>::value>::type
0377 #endif
0378     >
0379     chunk_body(
0380         ConstBufferSequence const& buffers,
0381         ChunkExtensions&& extensions);
0382 
0383     /** Constructor
0384 
0385         This constructs buffers representing a complete @em chunk
0386         with the passed chunk extensions and having the size and
0387         contents of the specified buffer sequence.
0388         The specified allocator is used to provide storage for the
0389         extensions object.
0390 
0391         @param buffers A buffer sequence representing the chunk
0392         body. Although the buffers object may be copied as necessary,
0393         ownership of the underlying memory blocks is retained by the
0394         caller, which must guarantee that they remain valid while this
0395         object is in use.
0396 
0397         @param extensions The chunk extensions object. The expression
0398         `extensions.str()` must be valid, and the return type must
0399         be convertible to @ref string_view. This object will be copied
0400         or moved as needed to ensure that the chunk header object retains
0401         ownership of the buffers provided by the chunk extensions object.
0402 
0403         @param allocator The allocator to provide storage for the moved
0404         or copied extensions object.
0405 
0406         @note This function participates in overload resolution only
0407         if @b ChunkExtensions meets the requirements stated above.
0408 
0409         @see https://tools.ietf.org/html/rfc7230#section-4.1
0410     */
0411     template<class ChunkExtensions, class Allocator
0412 #if ! BOOST_BEAST_DOXYGEN
0413         , class = typename std::enable_if<
0414             ! std::is_convertible<typename std::decay<
0415                 ChunkExtensions>::type, string_view>::value>::type
0416 #endif
0417     >
0418     chunk_body(
0419         ConstBufferSequence const& buffers,
0420         ChunkExtensions&& extensions,
0421         Allocator const& allocator);
0422 
0423     //-----
0424 
0425     /// Required for <em>ConstBufferSequence</em>
0426 #if BOOST_BEAST_DOXYGEN
0427     using value_type = __implementation_defined__;
0428 #else
0429     using value_type = typename view_type::value_type;
0430 #endif
0431 
0432     /// Required for <em>ConstBufferSequence</em>
0433 #if BOOST_BEAST_DOXYGEN
0434     using const_iterator = __implementation_defined__;
0435 #else
0436     using const_iterator = typename view_type::const_iterator;
0437 #endif
0438 
0439     /// Required for <em>ConstBufferSequence</em>
0440     const_iterator
0441     begin() const
0442     {
0443         return view_.begin();
0444     }
0445 
0446     /// Required for <em>ConstBufferSequence</em>
0447     const_iterator
0448     end() const
0449     {
0450         return view_.end();
0451     }
0452 };
0453 
0454 //------------------------------------------------------------------------------
0455 
0456 /** A chunked-encoding last chunk
0457 */
0458 template<class Trailer = chunk_crlf>
0459 class chunk_last
0460 {
0461     static_assert(
0462         is_fields<Trailer>::value ||
0463         net::is_const_buffer_sequence<Trailer>::value,
0464         "Trailer requirements not met");
0465 
0466     using buffers_type = typename
0467         detail::buffers_or_fields<Trailer>::type;
0468 
0469     using view_type =
0470         buffers_cat_view<
0471             detail::chunk_size0,    // "0\r\n"
0472             buffers_type>;          // Trailer (includes CRLF)
0473 
0474     template<class Allocator>
0475     buffers_type
0476     prepare(Trailer const& trailer, Allocator const& alloc);
0477 
0478     buffers_type
0479     prepare(Trailer const& trailer, std::true_type);
0480 
0481     buffers_type
0482     prepare(Trailer const& trailer, std::false_type);
0483 
0484     std::shared_ptr<void> sp_;
0485     view_type view_;
0486 
0487 public:
0488     /** Constructor
0489 
0490         The last chunk will have an empty trailer
0491     */
0492     chunk_last();
0493 
0494     /** Constructor
0495 
0496         @param trailer The trailer to use. This may be
0497         a type meeting the requirements of either Fields
0498         or ConstBufferSequence. If it is a ConstBufferSequence,
0499         the trailer must be formatted correctly as per rfc7230
0500         including a CRLF on its own line to denote the end
0501         of the trailer.
0502     */
0503     explicit
0504     chunk_last(Trailer const& trailer);
0505 
0506     /** Constructor
0507 
0508         @param trailer The trailer to use. This type must
0509         meet the requirements of Fields.
0510 
0511         @param allocator The allocator to use for storing temporary
0512         data associated with the serialized trailer buffers.
0513     */
0514 #if BOOST_BEAST_DOXYGEN
0515     template<class Allocator>
0516     chunk_last(Trailer const& trailer, Allocator const& allocator);
0517 #else
0518     template<class DeducedTrailer, class Allocator,
0519         class = typename std::enable_if<
0520             is_fields<DeducedTrailer>::value>::type>
0521     chunk_last(
0522         DeducedTrailer const& trailer, Allocator const& allocator);
0523 #endif
0524 
0525     //-----
0526 
0527     /// Required for <em>ConstBufferSequence</em>
0528     chunk_last(chunk_last const&) = default;
0529 
0530     /// Required for <em>ConstBufferSequence</em>
0531 #if BOOST_BEAST_DOXYGEN
0532     using value_type = __implementation_defined__;
0533 #else
0534     using value_type =
0535         typename view_type::value_type;
0536 #endif
0537 
0538     /// Required for <em>ConstBufferSequence</em>
0539 #if BOOST_BEAST_DOXYGEN
0540     using const_iterator = __implementation_defined__;
0541 #else
0542     using const_iterator =
0543         typename view_type::const_iterator;
0544 #endif
0545 
0546     /// Required for <em>ConstBufferSequence</em>
0547     const_iterator
0548     begin() const
0549     {
0550         return view_.begin();
0551     }
0552 
0553     /// Required for <em>ConstBufferSequence</em>
0554     const_iterator
0555     end() const
0556     {
0557         return view_.end();
0558     }
0559 };
0560 
0561 //------------------------------------------------------------------------------
0562 
0563 /** A set of chunk extensions
0564 
0565     This container stores a set of chunk extensions suited for use with
0566     @ref chunk_header and @ref chunk_body. The container may be iterated
0567     to access the extensions in their structured form.
0568 
0569     Meets the requirements of ChunkExtensions
0570 */
0571 template<class Allocator>
0572 class basic_chunk_extensions
0573 {
0574     std::basic_string<char,
0575         std::char_traits<char>, Allocator> s_;
0576 
0577     std::basic_string<char,
0578         std::char_traits<char>, Allocator> range_;
0579 
0580     template<class FwdIt>
0581     FwdIt
0582     do_parse(FwdIt it, FwdIt last, error_code& ec);
0583 
0584     void
0585     do_insert(string_view name, string_view value);
0586 
0587 public:
0588     /** The type of value when iterating.
0589 
0590         The first element of the pair is the name, and the second
0591         element is the value which may be empty. The value is
0592         stored in its raw representation, without quotes or escapes.
0593     */
0594     using value_type = std::pair<string_view, string_view>;
0595 
0596     class const_iterator;
0597 
0598     /// Constructor
0599     basic_chunk_extensions() = default;
0600 
0601     /// Constructor
0602     basic_chunk_extensions(basic_chunk_extensions&&) = default;
0603 
0604     /// Constructor
0605     basic_chunk_extensions(basic_chunk_extensions const&) = default;
0606 
0607     /** Constructor
0608 
0609         @param allocator The allocator to use for storing the serialized extension
0610     */
0611     explicit
0612     basic_chunk_extensions(Allocator const& allocator)
0613         : s_(allocator)
0614     {
0615     }
0616 
0617     /** Clear the chunk extensions
0618 
0619         This preserves the capacity of the internal string
0620         used to hold the serialized representation.
0621     */
0622     void
0623     clear()
0624     {
0625         s_.clear();
0626     }
0627 
0628     /** Parse a set of chunk extensions
0629 
0630         Any previous extensions will be cleared
0631     */
0632     void
0633     parse(string_view s, error_code& ec);
0634 
0635     /** Insert an extension name with an empty value
0636 
0637         @param name The name of the extension
0638     */
0639     void
0640     insert(string_view name);
0641 
0642     /** Insert an extension value
0643 
0644         @param name The name of the extension
0645 
0646         @param value The value to insert. Depending on the
0647         contents, the serialized extension may use a quoted string.
0648     */
0649     void
0650     insert(string_view name, string_view value);
0651 
0652     /// Return the serialized representation of the chunk extension
0653     string_view
0654     str() const
0655     {
0656         return s_;
0657     }
0658 
0659     const_iterator
0660     begin() const;
0661 
0662     const_iterator
0663     end() const;
0664 };
0665 
0666 //------------------------------------------------------------------------------
0667 
0668 /// A set of chunk extensions
0669 using chunk_extensions =
0670     basic_chunk_extensions<std::allocator<char>>;
0671 
0672 /** Returns a @ref chunk_body
0673 
0674     This functions constructs and returns a complete
0675     @ref chunk_body for a chunk body represented by the
0676     specified buffer sequence.
0677 
0678     @param buffers The buffers representing the chunk body.
0679 
0680     @param args Optional arguments passed to the @ref chunk_body constructor.
0681 
0682     @note This function is provided as a notational convenience
0683     to omit specification of the class template arguments.
0684 */
0685 template<class ConstBufferSequence, class... Args>
0686 auto
0687 make_chunk(
0688     ConstBufferSequence const& buffers,
0689     Args&&... args) ->
0690     chunk_body<ConstBufferSequence>
0691 {
0692     return chunk_body<ConstBufferSequence>(
0693         buffers, std::forward<Args>(args)...);
0694 }
0695 
0696 /** Returns a @ref chunk_last
0697 
0698     @note This function is provided as a notational convenience
0699     to omit specification of the class template arguments.
0700 */
0701 inline
0702 chunk_last<chunk_crlf>
0703 make_chunk_last()
0704 {
0705     return chunk_last<chunk_crlf>{};
0706 }
0707 
0708 /** Returns a @ref chunk_last
0709 
0710     This function construct and returns a complete
0711     @ref chunk_last for a last chunk containing the
0712     specified trailers.
0713 
0714     @param trailer A ConstBufferSequence or 
0715     @note This function is provided as a notational convenience
0716     to omit specification of the class template arguments.
0717 
0718     @param args Optional arguments passed to the @ref chunk_last
0719     constructor.
0720 */
0721 template<class Trailer, class... Args>
0722 chunk_last<Trailer>
0723 make_chunk_last(
0724     Trailer const& trailer,
0725     Args&&... args)
0726 {
0727     return chunk_last<Trailer>{
0728         trailer, std::forward<Args>(args)...};
0729 }
0730 
0731 } // http
0732 } // beast
0733 } // boost
0734 
0735 #include <boost/beast/http/impl/chunk_encode.hpp>
0736 
0737 #endif