123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- #ifndef ASIO_SSL_DETAIL_IO_HPP
- #define ASIO_SSL_DETAIL_IO_HPP
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif
- #include "asio/detail/config.hpp"
- #include "asio/detail/base_from_cancellation_state.hpp"
- #include "asio/detail/handler_tracking.hpp"
- #include "asio/ssl/detail/engine.hpp"
- #include "asio/ssl/detail/stream_core.hpp"
- #include "asio/write.hpp"
- #include "asio/detail/push_options.hpp"
- namespace asio {
- namespace ssl {
- namespace detail {
- template <typename Stream, typename Operation>
- std::size_t io(Stream& next_layer, stream_core& core,
- const Operation& op, asio::error_code& ec)
- {
- asio::error_code io_ec;
- std::size_t bytes_transferred = 0;
- do switch (op(core.engine_, ec, bytes_transferred))
- {
- case engine::want_input_and_retry:
-
-
- if (core.input_.size() == 0)
- {
- core.input_ = asio::buffer(core.input_buffer_,
- next_layer.read_some(core.input_buffer_, io_ec));
- if (!ec)
- ec = io_ec;
- }
-
- core.input_ = core.engine_.put_input(core.input_);
-
- continue;
- case engine::want_output_and_retry:
-
-
- asio::write(next_layer,
- core.engine_.get_output(core.output_buffer_), io_ec);
- if (!ec)
- ec = io_ec;
-
- continue;
- case engine::want_output:
-
-
- asio::write(next_layer,
- core.engine_.get_output(core.output_buffer_), io_ec);
- if (!ec)
- ec = io_ec;
-
- core.engine_.map_error_code(ec);
- return bytes_transferred;
- default:
-
- core.engine_.map_error_code(ec);
- return bytes_transferred;
- } while (!ec);
-
- core.engine_.map_error_code(ec);
- return 0;
- }
- template <typename Stream, typename Operation, typename Handler>
- class io_op
- : public asio::detail::base_from_cancellation_state<Handler>
- {
- public:
- io_op(Stream& next_layer, stream_core& core,
- const Operation& op, Handler& handler)
- : asio::detail::base_from_cancellation_state<Handler>(handler),
- next_layer_(next_layer),
- core_(core),
- op_(op),
- start_(0),
- want_(engine::want_nothing),
- bytes_transferred_(0),
- handler_(static_cast<Handler&&>(handler))
- {
- }
- io_op(const io_op& other)
- : asio::detail::base_from_cancellation_state<Handler>(other),
- next_layer_(other.next_layer_),
- core_(other.core_),
- op_(other.op_),
- start_(other.start_),
- want_(other.want_),
- ec_(other.ec_),
- bytes_transferred_(other.bytes_transferred_),
- handler_(other.handler_)
- {
- }
- io_op(io_op&& other)
- : asio::detail::base_from_cancellation_state<Handler>(
- static_cast<
- asio::detail::base_from_cancellation_state<Handler>&&>(other)),
- next_layer_(other.next_layer_),
- core_(other.core_),
- op_(static_cast<Operation&&>(other.op_)),
- start_(other.start_),
- want_(other.want_),
- ec_(other.ec_),
- bytes_transferred_(other.bytes_transferred_),
- handler_(static_cast<Handler&&>(other.handler_))
- {
- }
- void operator()(asio::error_code ec,
- std::size_t bytes_transferred = ~std::size_t(0), int start = 0)
- {
- switch (start_ = start)
- {
- case 1:
- do
- {
- switch (want_ = op_(core_.engine_, ec_, bytes_transferred_))
- {
- case engine::want_input_and_retry:
-
-
- if (core_.input_.size() != 0)
- {
- core_.input_ = core_.engine_.put_input(core_.input_);
- continue;
- }
-
-
-
-
- if (core_.expiry(core_.pending_read_) == core_.neg_infin())
- {
-
- core_.pending_read_.expires_at(core_.pos_infin());
- ASIO_HANDLER_LOCATION((
- __FILE__, __LINE__, Operation::tracking_name()));
-
- next_layer_.async_read_some(
- asio::buffer(core_.input_buffer_),
- static_cast<io_op&&>(*this));
- }
- else
- {
- ASIO_HANDLER_LOCATION((
- __FILE__, __LINE__, Operation::tracking_name()));
-
- core_.pending_read_.async_wait(static_cast<io_op&&>(*this));
- }
-
-
- return;
- case engine::want_output_and_retry:
- case engine::want_output:
-
-
-
-
- if (core_.expiry(core_.pending_write_) == core_.neg_infin())
- {
-
- core_.pending_write_.expires_at(core_.pos_infin());
- ASIO_HANDLER_LOCATION((
- __FILE__, __LINE__, Operation::tracking_name()));
-
- asio::async_write(next_layer_,
- core_.engine_.get_output(core_.output_buffer_),
- static_cast<io_op&&>(*this));
- }
- else
- {
- ASIO_HANDLER_LOCATION((
- __FILE__, __LINE__, Operation::tracking_name()));
-
- core_.pending_write_.async_wait(static_cast<io_op&&>(*this));
- }
-
-
- return;
- default:
-
-
-
-
-
- if (start)
- {
- ASIO_HANDLER_LOCATION((
- __FILE__, __LINE__, Operation::tracking_name()));
- next_layer_.async_read_some(
- asio::buffer(core_.input_buffer_, 0),
- static_cast<io_op&&>(*this));
-
-
- return;
- }
- else
- {
-
- break;
- }
- }
- default:
- if (bytes_transferred == ~std::size_t(0))
- bytes_transferred = 0;
- else if (!ec_)
- ec_ = ec;
- switch (want_)
- {
- case engine::want_input_and_retry:
-
- core_.input_ = asio::buffer(
- core_.input_buffer_, bytes_transferred);
- core_.input_ = core_.engine_.put_input(core_.input_);
-
- core_.pending_read_.expires_at(core_.neg_infin());
-
- if (this->cancelled() != cancellation_type::none)
- {
- ec_ = asio::error::operation_aborted;
- break;
- }
-
- continue;
- case engine::want_output_and_retry:
-
- core_.pending_write_.expires_at(core_.neg_infin());
-
- if (this->cancelled() != cancellation_type::none)
- {
- ec_ = asio::error::operation_aborted;
- break;
- }
-
- continue;
- case engine::want_output:
-
- core_.pending_write_.expires_at(core_.neg_infin());
-
- default:
-
- op_.call_handler(handler_,
- core_.engine_.map_error_code(ec_),
- ec_ ? 0 : bytes_transferred_);
-
- return;
- }
- } while (!ec_);
-
- op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0);
- }
- }
- Stream& next_layer_;
- stream_core& core_;
- Operation op_;
- int start_;
- engine::want want_;
- asio::error_code ec_;
- std::size_t bytes_transferred_;
- Handler handler_;
- };
- template <typename Stream, typename Operation, typename Handler>
- inline bool asio_handler_is_continuation(
- io_op<Stream, Operation, Handler>* this_handler)
- {
- return this_handler->start_ == 0 ? true
- : asio_handler_cont_helpers::is_continuation(this_handler->handler_);
- }
- template <typename Stream, typename Operation, typename Handler>
- inline void async_io(Stream& next_layer, stream_core& core,
- const Operation& op, Handler& handler)
- {
- io_op<Stream, Operation, Handler>(
- next_layer, core, op, handler)(
- asio::error_code(), 0, 1);
- }
- }
- }
- template <template <typename, typename> class Associator,
- typename Stream, typename Operation,
- typename Handler, typename DefaultCandidate>
- struct associator<Associator,
- ssl::detail::io_op<Stream, Operation, Handler>,
- DefaultCandidate>
- : Associator<Handler, DefaultCandidate>
- {
- static typename Associator<Handler, DefaultCandidate>::type get(
- const ssl::detail::io_op<Stream, Operation, Handler>& h) noexcept
- {
- return Associator<Handler, DefaultCandidate>::get(h.handler_);
- }
- static auto get(const ssl::detail::io_op<Stream, Operation, Handler>& h,
- const DefaultCandidate& c) noexcept
- -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c))
- {
- return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
- }
- };
- }
- #include "asio/detail/pop_options.hpp"
- #endif
|