in demo_example/asio/asio/ssl/detail/impl/engine.ipp [255:322]
engine::want engine::perform(int (engine::* op)(void*, std::size_t),
void* data, std::size_t length, asio::error_code& ec,
std::size_t* bytes_transferred)
{
std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_);
::ERR_clear_error();
int result = (this->*op)(data, length);
int ssl_error = ::SSL_get_error(ssl_, result);
int sys_error = static_cast<int>(::ERR_get_error());
std::size_t pending_output_after = ::BIO_ctrl_pending(ext_bio_);
if (ssl_error == SSL_ERROR_SSL)
{
ec = asio::error_code(sys_error,
asio::error::get_ssl_category());
return pending_output_after > pending_output_before
? want_output : want_nothing;
}
if (ssl_error == SSL_ERROR_SYSCALL)
{
if (sys_error == 0)
{
ec = asio::ssl::error::unspecified_system_error;
}
else
{
ec = asio::error_code(sys_error,
asio::error::get_ssl_category());
}
return pending_output_after > pending_output_before
? want_output : want_nothing;
}
if (result > 0 && bytes_transferred)
*bytes_transferred = static_cast<std::size_t>(result);
if (ssl_error == SSL_ERROR_WANT_WRITE)
{
ec = asio::error_code();
return want_output_and_retry;
}
else if (pending_output_after > pending_output_before)
{
ec = asio::error_code();
return result > 0 ? want_output : want_output_and_retry;
}
else if (ssl_error == SSL_ERROR_WANT_READ)
{
ec = asio::error_code();
return want_input_and_retry;
}
else if (ssl_error == SSL_ERROR_ZERO_RETURN)
{
ec = asio::error::eof;
return want_nothing;
}
else if (ssl_error == SSL_ERROR_NONE)
{
ec = asio::error_code();
return want_nothing;
}
else
{
ec = asio::ssl::error::unexpected_result;
return want_nothing;
}
}