engine::want engine::perform()

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;
  }
}