Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:35:48

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     template<class ReadHandler, class Buffers>
0171     void
0172     operator()(
0173         ReadHandler&& h,
0174         icy_stream* s,
0175         Buffers const& b)
0176     {
0177         // If you get an error on the following line it means
0178         // that your handler does not meet the documented type
0179         // requirements for the handler.
0180 
0181         static_assert(
0182             beast::detail::is_invocable<ReadHandler,
0183             void(error_code, std::size_t)>::value,
0184             "ReadHandler type requirements not met");
0185 
0186         read_op<
0187             Buffers,
0188             typename std::decay<ReadHandler>::type>(
0189                 std::forward<ReadHandler>(h), *s, b);
0190     }
0191 };
0192 
0193 };
0194 
0195 //------------------------------------------------------------------------------
0196 
0197 template<class NextLayer>
0198 template<class... Args>
0199 icy_stream<NextLayer>::
0200 icy_stream(Args&&... args)
0201     : stream_(std::forward<Args>(args)...)
0202 {
0203     std::memset(buf_, 0, sizeof(buf_));
0204 }
0205 
0206 template<class NextLayer>
0207 template<class MutableBufferSequence>
0208 std::size_t
0209 icy_stream<NextLayer>::
0210 read_some(MutableBufferSequence const& buffers)
0211 {
0212     static_assert(is_sync_read_stream<next_layer_type>::value,
0213         "SyncReadStream type requirements not met");
0214     static_assert(net::is_mutable_buffer_sequence<
0215         MutableBufferSequence>::value,
0216             "MutableBufferSequence type requirements not met");
0217     error_code ec;
0218     auto n = read_some(buffers, ec);
0219     if(ec)
0220         BOOST_THROW_EXCEPTION(system_error{ec});
0221     return n;
0222 }
0223 
0224 template<class NextLayer>
0225 template<class MutableBufferSequence>
0226 std::size_t
0227 icy_stream<NextLayer>::
0228 read_some(MutableBufferSequence const& buffers, error_code& ec)
0229 {
0230     static_assert(is_sync_read_stream<next_layer_type>::value,
0231         "SyncReadStream type requirements not met");
0232     static_assert(net::is_mutable_buffer_sequence<
0233         MutableBufferSequence>::value,
0234             "MutableBufferSequence type requirements not met");
0235     std::size_t bytes_transferred;
0236     if(detect_)
0237     {
0238         BOOST_ASSERT(n_ == 0);
0239         for(;;)
0240         {
0241             // Try to read the first three characters
0242             bytes_transferred = next_layer().read_some(
0243                 net::mutable_buffer(buf_ + n_, 3 - n_), ec);
0244             n_ += static_cast<char>(bytes_transferred);
0245             if(ec)
0246                 return 0;
0247             auto result = detail::is_icy(
0248                 net::const_buffer(buf_, n_));
0249             if(boost::indeterminate(result))
0250                 continue;
0251             if(result)
0252                 n_ = static_cast<char>(net::buffer_copy(
0253                     net::buffer(buf_, sizeof(buf_)),
0254                     icy_stream::version()));
0255             break;
0256         }
0257         detect_ = false;
0258     }
0259     if(n_ > 0)
0260     {
0261         bytes_transferred = net::buffer_copy(
0262             buffers, net::const_buffer(buf_, n_));
0263         n_ -= static_cast<char>(bytes_transferred);
0264         std::memmove(
0265             buf_,
0266             buf_ + bytes_transferred,
0267             sizeof(buf_) - bytes_transferred);
0268     }
0269     else
0270     {
0271         bytes_transferred =
0272             next_layer().read_some(buffers, ec);
0273     }
0274     return bytes_transferred;
0275 }
0276 
0277 template<class NextLayer>
0278 template<
0279     class MutableBufferSequence,
0280     BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
0281 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
0282 icy_stream<NextLayer>::
0283 async_read_some(
0284     MutableBufferSequence const& buffers,
0285     ReadHandler&& handler)
0286 {
0287     static_assert(is_async_read_stream<next_layer_type>::value,
0288         "AsyncReadStream type requirements not met");
0289     static_assert(net::is_mutable_buffer_sequence<
0290             MutableBufferSequence >::value,
0291         "MutableBufferSequence type requirements not met");
0292     return net::async_initiate<
0293         ReadHandler,
0294         void(error_code, std::size_t)>(
0295             typename ops::run_read_op{},
0296             handler,
0297             this,
0298             buffers);
0299 }
0300 
0301 template<class NextLayer>
0302 template<class MutableBufferSequence>
0303 std::size_t
0304 icy_stream<NextLayer>::
0305 write_some(MutableBufferSequence const& buffers)
0306 {
0307     static_assert(is_sync_write_stream<next_layer_type>::value,
0308         "SyncWriteStream type requirements not met");
0309     static_assert(net::is_const_buffer_sequence<
0310         MutableBufferSequence>::value,
0311             "MutableBufferSequence type requirements not met");
0312     return stream_.write_some(buffers);
0313 }
0314 
0315 template<class NextLayer>
0316 template<class MutableBufferSequence>
0317 std::size_t
0318 icy_stream<NextLayer>::
0319 write_some(MutableBufferSequence const& buffers, error_code& ec)
0320 {
0321     static_assert(is_sync_write_stream<next_layer_type>::value,
0322         "SyncWriteStream type requirements not met");
0323     static_assert(net::is_const_buffer_sequence<
0324         MutableBufferSequence>::value,
0325             "MutableBufferSequence type requirements not met");
0326     return stream_.write_some(buffers, ec);
0327 }
0328 
0329 template<class NextLayer>
0330 template<
0331     class MutableBufferSequence,
0332     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0333 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0334 icy_stream<NextLayer>::
0335 async_write_some(
0336     MutableBufferSequence const& buffers,
0337     WriteHandler&& handler)
0338 {
0339     static_assert(is_async_write_stream<next_layer_type>::value,
0340         "AsyncWriteStream type requirements not met");
0341     static_assert(net::is_const_buffer_sequence<
0342             MutableBufferSequence>::value,
0343         "MutableBufferSequence type requirements not met");
0344     return stream_.async_write_some(
0345         buffers, std::forward<WriteHandler>(handler));
0346 }
0347 
0348 } // http
0349 } // beast
0350 } // boost
0351 
0352 #endif