Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:27:52

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_CORE_IMPL_ICY_STREAM_HPP
0011 #define BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP
0012 
0013 #include <boost/beast/core/async_base.hpp>
0014 #include <boost/beast/core/buffer_traits.hpp>
0015 #include <boost/beast/core/error.hpp>
0016 #include <boost/beast/core/stream_traits.hpp>
0017 #include <boost/beast/core/detail/is_invocable.hpp>
0018 #include <boost/asio/coroutine.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/throw_exception.hpp>
0021 #include <cstring>
0022 #include <memory>
0023 #include <utility>
0024 
0025 namespace boost {
0026 namespace beast {
0027 namespace http {
0028 
0029 namespace detail {
0030 
0031 template<class ConstBufferSequence>
0032 boost::tribool
0033 is_icy(ConstBufferSequence const& buffers)
0034 {
0035     char buf[3];
0036     auto const n = net::buffer_copy(
0037         net::mutable_buffer(buf, 3),
0038         buffers);
0039     if(n >= 1 && buf[0] != 'I')
0040         return false;
0041     if(n >= 2 && buf[1] != 'C')
0042         return false;
0043     if(n >= 3 && buf[2] != 'Y')
0044         return false;
0045     if(n < 3)
0046         return boost::indeterminate;
0047     return true;
0048 }
0049 
0050 } // detail
0051 
0052 template<class NextLayer>
0053 struct icy_stream<NextLayer>::ops
0054 {
0055 
0056 template<class Buffers, class Handler>
0057 class read_op
0058     : public beast::async_base<Handler,
0059         beast::executor_type<icy_stream>>
0060     , public asio::coroutine
0061 {
0062     icy_stream& s_;
0063     Buffers b_;
0064     std::size_t n_ = 0;
0065     error_code ec_;
0066     bool match_ = false;
0067 
0068 public:
0069     template<class Handler_>
0070     read_op(
0071         Handler_&& h,
0072         icy_stream& s,
0073         Buffers const& b)
0074         : async_base<Handler,
0075             beast::executor_type<icy_stream>>(
0076                 std::forward<Handler_>(h), s.get_executor())
0077         , s_(s)
0078         , b_(b)
0079     {
0080         (*this)({}, 0, false);
0081     }
0082 
0083     void
0084     operator()(
0085         error_code ec,
0086         std::size_t bytes_transferred,
0087         bool cont = true)
0088     {
0089         BOOST_ASIO_CORO_REENTER(*this)
0090         {
0091             if(s_.detect_)
0092             {
0093                 BOOST_ASSERT(s_.n_ == 0);
0094                 for(;;)
0095                 {
0096                     // Try to read the first three characters
0097                     BOOST_ASIO_CORO_YIELD
0098                     {
0099                         BOOST_ASIO_HANDLER_LOCATION((
0100                             __FILE__, __LINE__,
0101                             "http::icy_stream::async_read_some"));
0102 
0103                         s_.next_layer().async_read_some(
0104                             net::mutable_buffer(
0105                                 s_.buf_ + s_.n_, 3 - s_.n_),
0106                             std::move(*this));
0107                     }
0108                     s_.n_ += static_cast<char>(bytes_transferred);
0109                     if(ec)
0110                         goto upcall;
0111                     auto result = detail::is_icy(
0112                         net::const_buffer(s_.buf_, s_.n_));
0113                     if(boost::indeterminate(result))
0114                         continue;
0115                     if(result)
0116                         s_.n_ = static_cast<char>(net::buffer_copy(
0117                             net::buffer(s_.buf_, sizeof(s_.buf_)),
0118                             icy_stream::version()));
0119                     break;
0120                 }
0121                 s_.detect_ = false;
0122             }
0123             if(s_.n_ > 0)
0124             {
0125                 bytes_transferred = net::buffer_copy(
0126                     b_, net::const_buffer(s_.buf_, s_.n_));
0127                 s_.n_ -= static_cast<char>(bytes_transferred);
0128                 std::memmove(
0129                     s_.buf_,
0130                     s_.buf_ + bytes_transferred,
0131                     sizeof(s_.buf_) - bytes_transferred);
0132             }
0133             else
0134             {
0135                 BOOST_ASIO_CORO_YIELD
0136                 {
0137                     BOOST_ASIO_HANDLER_LOCATION((
0138                         __FILE__, __LINE__,
0139                         "http::icy_stream::async_read_some"));
0140 
0141                     s_.next_layer().async_read_some(
0142                         b_, std::move(*this));
0143                 }
0144             }
0145         upcall:
0146             if(! cont)
0147             {
0148                 ec_ = ec;
0149                 n_ = bytes_transferred;
0150                 BOOST_ASIO_CORO_YIELD
0151                 {
0152                     BOOST_ASIO_HANDLER_LOCATION((
0153                         __FILE__, __LINE__,
0154                         "http::icy_stream::async_read_some"));
0155 
0156                     s_.next_layer().async_read_some(
0157                         net::mutable_buffer{},
0158                         std::move(*this));
0159                 }
0160                 BOOST_BEAST_ASSIGN_EC(ec, ec_);
0161                 bytes_transferred = n_;
0162             }
0163             this->complete_now(ec, bytes_transferred);
0164         }
0165     }
0166 };
0167 
0168 struct run_read_op
0169 {
0170     icy_stream* self;
0171 
0172     using executor_type = typename icy_stream::executor_type;
0173 
0174     executor_type
0175     get_executor() const noexcept
0176     {
0177         return self->get_executor();
0178     }
0179 
0180     template<class ReadHandler, class Buffers>
0181     void
0182     operator()(
0183         ReadHandler&& h,
0184         Buffers const& b)
0185     {
0186         // If you get an error on the following line it means
0187         // that your handler does not meet the documented type
0188         // requirements for the handler.
0189 
0190         static_assert(
0191             beast::detail::is_invocable<ReadHandler,
0192             void(error_code, std::size_t)>::value,
0193             "ReadHandler type requirements not met");
0194 
0195         read_op<
0196             Buffers,
0197             typename std::decay<ReadHandler>::type>(
0198                 std::forward<ReadHandler>(h), *self, b);
0199     }
0200 };
0201 
0202 };
0203 
0204 //------------------------------------------------------------------------------
0205 
0206 template<class NextLayer>
0207 template<class... Args>
0208 icy_stream<NextLayer>::
0209 icy_stream(Args&&... args)
0210     : stream_(std::forward<Args>(args)...)
0211 {
0212     std::memset(buf_, 0, sizeof(buf_));
0213 }
0214 
0215 template<class NextLayer>
0216 template<class MutableBufferSequence>
0217 std::size_t
0218 icy_stream<NextLayer>::
0219 read_some(MutableBufferSequence const& buffers)
0220 {
0221     static_assert(is_sync_read_stream<next_layer_type>::value,
0222         "SyncReadStream type requirements not met");
0223     static_assert(net::is_mutable_buffer_sequence<
0224         MutableBufferSequence>::value,
0225             "MutableBufferSequence type requirements not met");
0226     error_code ec;
0227     auto n = read_some(buffers, ec);
0228     if(ec)
0229         BOOST_THROW_EXCEPTION(system_error{ec});
0230     return n;
0231 }
0232 
0233 template<class NextLayer>
0234 template<class MutableBufferSequence>
0235 std::size_t
0236 icy_stream<NextLayer>::
0237 read_some(MutableBufferSequence const& buffers, error_code& ec)
0238 {
0239     static_assert(is_sync_read_stream<next_layer_type>::value,
0240         "SyncReadStream type requirements not met");
0241     static_assert(net::is_mutable_buffer_sequence<
0242         MutableBufferSequence>::value,
0243             "MutableBufferSequence type requirements not met");
0244     std::size_t bytes_transferred;
0245     if(detect_)
0246     {
0247         BOOST_ASSERT(n_ == 0);
0248         for(;;)
0249         {
0250             // Try to read the first three characters
0251             bytes_transferred = next_layer().read_some(
0252                 net::mutable_buffer(buf_ + n_, 3 - n_), ec);
0253             n_ += static_cast<char>(bytes_transferred);
0254             if(ec)
0255                 return 0;
0256             auto result = detail::is_icy(
0257                 net::const_buffer(buf_, n_));
0258             if(boost::indeterminate(result))
0259                 continue;
0260             if(result)
0261                 n_ = static_cast<char>(net::buffer_copy(
0262                     net::buffer(buf_, sizeof(buf_)),
0263                     icy_stream::version()));
0264             break;
0265         }
0266         detect_ = false;
0267     }
0268     if(n_ > 0)
0269     {
0270         bytes_transferred = net::buffer_copy(
0271             buffers, net::const_buffer(buf_, n_));
0272         n_ -= static_cast<char>(bytes_transferred);
0273         std::memmove(
0274             buf_,
0275             buf_ + bytes_transferred,
0276             sizeof(buf_) - bytes_transferred);
0277     }
0278     else
0279     {
0280         bytes_transferred =
0281             next_layer().read_some(buffers, ec);
0282     }
0283     return bytes_transferred;
0284 }
0285 
0286 template<class NextLayer>
0287 template<
0288     class MutableBufferSequence,
0289     BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
0290 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
0291 icy_stream<NextLayer>::
0292 async_read_some(
0293     MutableBufferSequence const& buffers,
0294     ReadHandler&& handler)
0295 {
0296     static_assert(is_async_read_stream<next_layer_type>::value,
0297         "AsyncReadStream type requirements not met");
0298     static_assert(net::is_mutable_buffer_sequence<
0299             MutableBufferSequence >::value,
0300         "MutableBufferSequence type requirements not met");
0301     return net::async_initiate<
0302         ReadHandler,
0303         void(error_code, std::size_t)>(
0304             typename ops::run_read_op{this},
0305             handler,
0306             buffers);
0307 }
0308 
0309 template<class NextLayer>
0310 template<class MutableBufferSequence>
0311 std::size_t
0312 icy_stream<NextLayer>::
0313 write_some(MutableBufferSequence const& buffers)
0314 {
0315     static_assert(is_sync_write_stream<next_layer_type>::value,
0316         "SyncWriteStream type requirements not met");
0317     static_assert(net::is_const_buffer_sequence<
0318         MutableBufferSequence>::value,
0319             "MutableBufferSequence type requirements not met");
0320     return stream_.write_some(buffers);
0321 }
0322 
0323 template<class NextLayer>
0324 template<class MutableBufferSequence>
0325 std::size_t
0326 icy_stream<NextLayer>::
0327 write_some(MutableBufferSequence const& buffers, error_code& ec)
0328 {
0329     static_assert(is_sync_write_stream<next_layer_type>::value,
0330         "SyncWriteStream type requirements not met");
0331     static_assert(net::is_const_buffer_sequence<
0332         MutableBufferSequence>::value,
0333             "MutableBufferSequence type requirements not met");
0334     return stream_.write_some(buffers, ec);
0335 }
0336 
0337 template<class NextLayer>
0338 template<
0339     class MutableBufferSequence,
0340     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0341 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0342 icy_stream<NextLayer>::
0343 async_write_some(
0344     MutableBufferSequence const& buffers,
0345     WriteHandler&& handler)
0346 {
0347     static_assert(is_async_write_stream<next_layer_type>::value,
0348         "AsyncWriteStream type requirements not met");
0349     static_assert(net::is_const_buffer_sequence<
0350             MutableBufferSequence>::value,
0351         "MutableBufferSequence type requirements not met");
0352     return stream_.async_write_some(
0353         buffers, std::forward<WriteHandler>(handler));
0354 }
0355 
0356 } // http
0357 } // beast
0358 } // boost
0359 
0360 #endif