File indexing completed on 2025-01-18 09:29:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_SSL_DETAIL_IO_HPP
0012 #define BOOST_ASIO_SSL_DETAIL_IO_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0021 #include <boost/asio/detail/handler_tracking.hpp>
0022 #include <boost/asio/ssl/detail/engine.hpp>
0023 #include <boost/asio/ssl/detail/stream_core.hpp>
0024 #include <boost/asio/write.hpp>
0025
0026 #include <boost/asio/detail/push_options.hpp>
0027
0028 namespace boost {
0029 namespace asio {
0030 namespace ssl {
0031 namespace detail {
0032
0033 template <typename Stream, typename Operation>
0034 std::size_t io(Stream& next_layer, stream_core& core,
0035 const Operation& op, boost::system::error_code& ec)
0036 {
0037 boost::system::error_code io_ec;
0038 std::size_t bytes_transferred = 0;
0039 do switch (op(core.engine_, ec, bytes_transferred))
0040 {
0041 case engine::want_input_and_retry:
0042
0043
0044
0045 if (core.input_.size() == 0)
0046 {
0047 core.input_ = boost::asio::buffer(core.input_buffer_,
0048 next_layer.read_some(core.input_buffer_, io_ec));
0049 if (!ec)
0050 ec = io_ec;
0051 }
0052
0053
0054 core.input_ = core.engine_.put_input(core.input_);
0055
0056
0057 continue;
0058
0059 case engine::want_output_and_retry:
0060
0061
0062
0063 boost::asio::write(next_layer,
0064 core.engine_.get_output(core.output_buffer_), io_ec);
0065 if (!ec)
0066 ec = io_ec;
0067
0068
0069 continue;
0070
0071 case engine::want_output:
0072
0073
0074
0075 boost::asio::write(next_layer,
0076 core.engine_.get_output(core.output_buffer_), io_ec);
0077 if (!ec)
0078 ec = io_ec;
0079
0080
0081 core.engine_.map_error_code(ec);
0082 return bytes_transferred;
0083
0084 default:
0085
0086
0087 core.engine_.map_error_code(ec);
0088 return bytes_transferred;
0089
0090 } while (!ec);
0091
0092
0093 core.engine_.map_error_code(ec);
0094 return 0;
0095 }
0096
0097 template <typename Stream, typename Operation, typename Handler>
0098 class io_op
0099 : public boost::asio::detail::base_from_cancellation_state<Handler>
0100 {
0101 public:
0102 io_op(Stream& next_layer, stream_core& core,
0103 const Operation& op, Handler& handler)
0104 : boost::asio::detail::base_from_cancellation_state<Handler>(handler),
0105 next_layer_(next_layer),
0106 core_(core),
0107 op_(op),
0108 start_(0),
0109 want_(engine::want_nothing),
0110 bytes_transferred_(0),
0111 handler_(static_cast<Handler&&>(handler))
0112 {
0113 }
0114
0115 io_op(const io_op& other)
0116 : boost::asio::detail::base_from_cancellation_state<Handler>(other),
0117 next_layer_(other.next_layer_),
0118 core_(other.core_),
0119 op_(other.op_),
0120 start_(other.start_),
0121 want_(other.want_),
0122 ec_(other.ec_),
0123 bytes_transferred_(other.bytes_transferred_),
0124 handler_(other.handler_)
0125 {
0126 }
0127
0128 io_op(io_op&& other)
0129 : boost::asio::detail::base_from_cancellation_state<Handler>(
0130 static_cast<
0131 boost::asio::detail::base_from_cancellation_state<Handler>&&>(other)),
0132 next_layer_(other.next_layer_),
0133 core_(other.core_),
0134 op_(static_cast<Operation&&>(other.op_)),
0135 start_(other.start_),
0136 want_(other.want_),
0137 ec_(other.ec_),
0138 bytes_transferred_(other.bytes_transferred_),
0139 handler_(static_cast<Handler&&>(other.handler_))
0140 {
0141 }
0142
0143 void operator()(boost::system::error_code ec,
0144 std::size_t bytes_transferred = ~std::size_t(0), int start = 0)
0145 {
0146 switch (start_ = start)
0147 {
0148 case 1:
0149 do
0150 {
0151 switch (want_ = op_(core_.engine_, ec_, bytes_transferred_))
0152 {
0153 case engine::want_input_and_retry:
0154
0155
0156
0157 if (core_.input_.size() != 0)
0158 {
0159 core_.input_ = core_.engine_.put_input(core_.input_);
0160 continue;
0161 }
0162
0163
0164
0165
0166
0167 if (core_.expiry(core_.pending_read_) == core_.neg_infin())
0168 {
0169
0170 core_.pending_read_.expires_at(core_.pos_infin());
0171
0172 BOOST_ASIO_HANDLER_LOCATION((
0173 __FILE__, __LINE__, Operation::tracking_name()));
0174
0175
0176 next_layer_.async_read_some(
0177 boost::asio::buffer(core_.input_buffer_),
0178 static_cast<io_op&&>(*this));
0179 }
0180 else
0181 {
0182 BOOST_ASIO_HANDLER_LOCATION((
0183 __FILE__, __LINE__, Operation::tracking_name()));
0184
0185
0186 core_.pending_read_.async_wait(static_cast<io_op&&>(*this));
0187 }
0188
0189
0190
0191 return;
0192
0193 case engine::want_output_and_retry:
0194 case engine::want_output:
0195
0196
0197
0198
0199
0200 if (core_.expiry(core_.pending_write_) == core_.neg_infin())
0201 {
0202
0203 core_.pending_write_.expires_at(core_.pos_infin());
0204
0205 BOOST_ASIO_HANDLER_LOCATION((
0206 __FILE__, __LINE__, Operation::tracking_name()));
0207
0208
0209 boost::asio::async_write(next_layer_,
0210 core_.engine_.get_output(core_.output_buffer_),
0211 static_cast<io_op&&>(*this));
0212 }
0213 else
0214 {
0215 BOOST_ASIO_HANDLER_LOCATION((
0216 __FILE__, __LINE__, Operation::tracking_name()));
0217
0218
0219 core_.pending_write_.async_wait(static_cast<io_op&&>(*this));
0220 }
0221
0222
0223
0224 return;
0225
0226 default:
0227
0228
0229
0230
0231
0232
0233 if (start)
0234 {
0235 BOOST_ASIO_HANDLER_LOCATION((
0236 __FILE__, __LINE__, Operation::tracking_name()));
0237
0238 next_layer_.async_read_some(
0239 boost::asio::buffer(core_.input_buffer_, 0),
0240 static_cast<io_op&&>(*this));
0241
0242
0243
0244 return;
0245 }
0246 else
0247 {
0248
0249 break;
0250 }
0251 }
0252
0253 default:
0254 if (bytes_transferred == ~std::size_t(0))
0255 bytes_transferred = 0;
0256 else if (!ec_)
0257 ec_ = ec;
0258
0259 switch (want_)
0260 {
0261 case engine::want_input_and_retry:
0262
0263
0264 core_.input_ = boost::asio::buffer(
0265 core_.input_buffer_, bytes_transferred);
0266 core_.input_ = core_.engine_.put_input(core_.input_);
0267
0268
0269 core_.pending_read_.expires_at(core_.neg_infin());
0270
0271
0272 if (this->cancelled() != cancellation_type::none)
0273 {
0274 ec_ = boost::asio::error::operation_aborted;
0275 break;
0276 }
0277
0278
0279 continue;
0280
0281 case engine::want_output_and_retry:
0282
0283
0284 core_.pending_write_.expires_at(core_.neg_infin());
0285
0286
0287 if (this->cancelled() != cancellation_type::none)
0288 {
0289 ec_ = boost::asio::error::operation_aborted;
0290 break;
0291 }
0292
0293
0294 continue;
0295
0296 case engine::want_output:
0297
0298
0299 core_.pending_write_.expires_at(core_.neg_infin());
0300
0301
0302
0303 default:
0304
0305
0306 op_.call_handler(handler_,
0307 core_.engine_.map_error_code(ec_),
0308 ec_ ? 0 : bytes_transferred_);
0309
0310
0311 return;
0312 }
0313 } while (!ec_);
0314
0315
0316 op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0);
0317 }
0318 }
0319
0320
0321 Stream& next_layer_;
0322 stream_core& core_;
0323 Operation op_;
0324 int start_;
0325 engine::want want_;
0326 boost::system::error_code ec_;
0327 std::size_t bytes_transferred_;
0328 Handler handler_;
0329 };
0330
0331 template <typename Stream, typename Operation, typename Handler>
0332 inline bool asio_handler_is_continuation(
0333 io_op<Stream, Operation, Handler>* this_handler)
0334 {
0335 return this_handler->start_ == 0 ? true
0336 : boost_asio_handler_cont_helpers::is_continuation(this_handler->handler_);
0337 }
0338
0339 template <typename Stream, typename Operation, typename Handler>
0340 inline void async_io(Stream& next_layer, stream_core& core,
0341 const Operation& op, Handler& handler)
0342 {
0343 io_op<Stream, Operation, Handler>(
0344 next_layer, core, op, handler)(
0345 boost::system::error_code(), 0, 1);
0346 }
0347
0348 }
0349 }
0350
0351 template <template <typename, typename> class Associator,
0352 typename Stream, typename Operation,
0353 typename Handler, typename DefaultCandidate>
0354 struct associator<Associator,
0355 ssl::detail::io_op<Stream, Operation, Handler>,
0356 DefaultCandidate>
0357 : Associator<Handler, DefaultCandidate>
0358 {
0359 static typename Associator<Handler, DefaultCandidate>::type get(
0360 const ssl::detail::io_op<Stream, Operation, Handler>& h) noexcept
0361 {
0362 return Associator<Handler, DefaultCandidate>::get(h.handler_);
0363 }
0364
0365 static auto get(const ssl::detail::io_op<Stream, Operation, Handler>& h,
0366 const DefaultCandidate& c) noexcept
0367 -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c))
0368 {
0369 return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
0370 }
0371 };
0372
0373 }
0374 }
0375
0376 #include <boost/asio/detail/pop_options.hpp>
0377
0378 #endif