File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
0011 #define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
0012
0013 #include <boost/beast/core/async_base.hpp>
0014 #include <boost/beast/core/buffers_prefix.hpp>
0015 #include <boost/beast/core/static_buffer.hpp>
0016 #include <boost/beast/core/stream_traits.hpp>
0017 #include <boost/beast/websocket/teardown.hpp>
0018 #include <boost/asio/buffer.hpp>
0019 #include <memory>
0020
0021 namespace boost {
0022 namespace beast {
0023
0024 template<class NextLayer>
0025 struct flat_stream<NextLayer>::ops
0026 {
0027
0028 template<class Handler>
0029 class write_op
0030 : public async_base<Handler,
0031 beast::executor_type<flat_stream>>
0032 {
0033 public:
0034 template<
0035 class ConstBufferSequence,
0036 class Handler_>
0037 write_op(
0038 Handler_&& h,
0039 flat_stream<NextLayer>& s,
0040 ConstBufferSequence const& b)
0041 : async_base<Handler,
0042 beast::executor_type<flat_stream>>(
0043 std::forward<Handler_>(h),
0044 s.get_executor())
0045 {
0046 auto const result =
0047 flatten(b, max_size);
0048 if(result.flatten)
0049 {
0050 s.buffer_.clear();
0051 s.buffer_.commit(net::buffer_copy(
0052 s.buffer_.prepare(result.size),
0053 b, result.size));
0054
0055 BOOST_ASIO_HANDLER_LOCATION((
0056 __FILE__, __LINE__,
0057 "flat_stream::async_write_some"));
0058
0059 s.stream_.async_write_some(
0060 s.buffer_.data(), std::move(*this));
0061 }
0062 else
0063 {
0064 s.buffer_.clear();
0065 s.buffer_.shrink_to_fit();
0066
0067 BOOST_ASIO_HANDLER_LOCATION((
0068 __FILE__, __LINE__,
0069 "flat_stream::async_write_some"));
0070
0071 s.stream_.async_write_some(
0072 beast::buffers_prefix(
0073 result.size, b), std::move(*this));
0074 }
0075 }
0076
0077 void
0078 operator()(
0079 boost::system::error_code ec,
0080 std::size_t bytes_transferred)
0081 {
0082 this->complete_now(ec, bytes_transferred);
0083 }
0084 };
0085
0086 struct run_write_op
0087 {
0088 template<class WriteHandler, class Buffers>
0089 void
0090 operator()(
0091 WriteHandler&& h,
0092 flat_stream* s,
0093 Buffers const& b)
0094 {
0095
0096
0097
0098
0099 static_assert(
0100 beast::detail::is_invocable<WriteHandler,
0101 void(error_code, std::size_t)>::value,
0102 "WriteHandler type requirements not met");
0103
0104 write_op<
0105 typename std::decay<WriteHandler>::type>(
0106 std::forward<WriteHandler>(h), *s, b);
0107 }
0108 };
0109
0110 };
0111
0112
0113
0114 template<class NextLayer>
0115 template<class... Args>
0116 flat_stream<NextLayer>::
0117 flat_stream(Args&&... args)
0118 : stream_(std::forward<Args>(args)...)
0119 {
0120 }
0121
0122 template<class NextLayer>
0123 template<class MutableBufferSequence>
0124 std::size_t
0125 flat_stream<NextLayer>::
0126 read_some(MutableBufferSequence const& buffers)
0127 {
0128 static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
0129 "SyncReadStream type requirements not met");
0130 static_assert(net::is_mutable_buffer_sequence<
0131 MutableBufferSequence>::value,
0132 "MutableBufferSequence type requirements not met");
0133 error_code ec;
0134 auto n = read_some(buffers, ec);
0135 if(ec)
0136 BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
0137 return n;
0138 }
0139
0140 template<class NextLayer>
0141 template<class MutableBufferSequence>
0142 std::size_t
0143 flat_stream<NextLayer>::
0144 read_some(MutableBufferSequence const& buffers, error_code& ec)
0145 {
0146 static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
0147 "SyncReadStream type requirements not met");
0148 static_assert(net::is_mutable_buffer_sequence<
0149 MutableBufferSequence>::value,
0150 "MutableBufferSequence type requirements not met");
0151 return stream_.read_some(buffers, ec);
0152 }
0153
0154 template<class NextLayer>
0155 template<
0156 class MutableBufferSequence,
0157 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
0158 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
0159 flat_stream<NextLayer>::
0160 async_read_some(
0161 MutableBufferSequence const& buffers,
0162 ReadHandler&& handler)
0163 {
0164 static_assert(boost::beast::is_async_read_stream<next_layer_type>::value,
0165 "AsyncReadStream type requirements not met");
0166 static_assert(net::is_mutable_buffer_sequence<
0167 MutableBufferSequence >::value,
0168 "MutableBufferSequence type requirements not met");
0169 return stream_.async_read_some(
0170 buffers, std::forward<ReadHandler>(handler));
0171 }
0172
0173 template<class NextLayer>
0174 template<class ConstBufferSequence>
0175 std::size_t
0176 flat_stream<NextLayer>::
0177 write_some(ConstBufferSequence const& buffers)
0178 {
0179 static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
0180 "SyncWriteStream type requirements not met");
0181 static_assert(net::is_const_buffer_sequence<
0182 ConstBufferSequence>::value,
0183 "ConstBufferSequence type requirements not met");
0184 error_code ec;
0185 auto n = write_some(buffers, ec);
0186 if(ec)
0187 BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
0188 return n;
0189 }
0190
0191 template<class NextLayer>
0192 template<class ConstBufferSequence>
0193 std::size_t
0194 flat_stream<NextLayer>::
0195 stack_write_some(
0196 std::size_t size,
0197 ConstBufferSequence const& buffers,
0198 error_code& ec)
0199 {
0200 static_buffer<max_stack> b;
0201 b.commit(net::buffer_copy(
0202 b.prepare(size), buffers));
0203 return stream_.write_some(b.data(), ec);
0204 }
0205
0206 template<class NextLayer>
0207 template<class ConstBufferSequence>
0208 std::size_t
0209 flat_stream<NextLayer>::
0210 write_some(ConstBufferSequence const& buffers, error_code& ec)
0211 {
0212 static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
0213 "SyncWriteStream type requirements not met");
0214 static_assert(net::is_const_buffer_sequence<
0215 ConstBufferSequence>::value,
0216 "ConstBufferSequence type requirements not met");
0217 auto const result = flatten(buffers, max_size);
0218 if(result.flatten)
0219 {
0220 if(result.size <= max_stack)
0221 return stack_write_some(result.size, buffers, ec);
0222
0223 buffer_.clear();
0224 buffer_.commit(net::buffer_copy(
0225 buffer_.prepare(result.size),
0226 buffers));
0227 return stream_.write_some(buffer_.data(), ec);
0228 }
0229 buffer_.clear();
0230 buffer_.shrink_to_fit();
0231 return stream_.write_some(
0232 boost::beast::buffers_prefix(result.size, buffers), ec);
0233 }
0234
0235 template<class NextLayer>
0236 template<
0237 class ConstBufferSequence,
0238 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0239 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0240 flat_stream<NextLayer>::
0241 async_write_some(
0242 ConstBufferSequence const& buffers,
0243 WriteHandler&& handler)
0244 {
0245 static_assert(boost::beast::is_async_write_stream<next_layer_type>::value,
0246 "AsyncWriteStream type requirements not met");
0247 static_assert(net::is_const_buffer_sequence<
0248 ConstBufferSequence>::value,
0249 "ConstBufferSequence type requirements not met");
0250 return net::async_initiate<
0251 WriteHandler,
0252 void(error_code, std::size_t)>(
0253 typename ops::run_write_op{},
0254 handler,
0255 this,
0256 buffers);
0257 }
0258
0259 template<class NextLayer>
0260 void
0261 teardown(
0262 boost::beast::role_type role,
0263 flat_stream<NextLayer>& s,
0264 error_code& ec)
0265 {
0266 using boost::beast::websocket::teardown;
0267 teardown(role, s.next_layer(), ec);
0268 }
0269
0270 template<class NextLayer, class TeardownHandler>
0271 void
0272 async_teardown(
0273 boost::beast::role_type role,
0274 flat_stream<NextLayer>& s,
0275 TeardownHandler&& handler)
0276 {
0277 using boost::beast::websocket::async_teardown;
0278 async_teardown(role, s.next_layer(), std::move(handler));
0279 }
0280
0281 }
0282 }
0283
0284 #endif