| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- //
- // Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef BOOST_MQTT5_ANY_AUTHENTICATOR
- #define BOOST_MQTT5_ANY_AUTHENTICATOR
- #include <boost/mqtt5/types.hpp>
- #include <boost/asio/any_completion_handler.hpp>
- #include <boost/asio/async_result.hpp>
- #include <boost/system/error_code.hpp>
- #include <boost/type_traits/is_detected.hpp>
- #include <boost/type_traits/is_detected_convertible.hpp>
- #include <memory>
- #include <string>
- #include <string_view>
- #include <type_traits>
- namespace boost::mqtt5::detail {
- namespace asio = boost::asio;
- using error_code = boost::system::error_code;
- using auth_handler_type = asio::any_completion_handler<
- void (error_code, std::string)
- >;
- template <typename T, typename ...Ts>
- using async_auth_sig = decltype(
- std::declval<T>().async_auth(std::declval<Ts>()...)
- );
- template <typename T>
- using method_sig = decltype(
- std::declval<T>().method()
- );
- template <typename T>
- constexpr bool is_authenticator =
- boost::is_detected<
- async_auth_sig, T,
- auth_step_e, std::string, auth_handler_type
- >::value &&
- boost::is_detected_convertible_v<std::string_view, method_sig, T>;
- class auth_fun_base {
- using auth_func = void(*)(
- auth_step_e, std::string, auth_handler_type, auth_fun_base*
- );
- auth_func _auth_func;
- public:
- auth_fun_base(auth_func f) : _auth_func(f) {}
- ~auth_fun_base() = default;
- void async_auth(
- auth_step_e step, std::string data,
- auth_handler_type auth_handler
- ) {
- _auth_func(step, std::move(data), std::move(auth_handler), this);
- }
- };
- template <
- typename Authenticator,
- typename = std::enable_if_t<is_authenticator<Authenticator>>
- >
- class auth_fun : public auth_fun_base {
- Authenticator _authenticator;
- public:
- auth_fun(Authenticator authenticator) :
- auth_fun_base(&async_auth),
- _authenticator(std::forward<Authenticator>(authenticator))
- {}
- static void async_auth(
- auth_step_e step, std::string data, auth_handler_type auth_handler,
- auth_fun_base* base_ptr
- ) {
- auto auth_fun_ptr = static_cast<auth_fun*>(base_ptr);
- auth_fun_ptr->_authenticator.async_auth(
- step, std::move(data), std::move(auth_handler)
- );
- }
- };
- class any_authenticator {
- std::string _method;
- std::shared_ptr<detail::auth_fun_base> _auth_fun;
- public:
- any_authenticator() = default;
- template <
- typename Authenticator,
- std::enable_if_t<detail::is_authenticator<Authenticator>, bool> = true
- >
- any_authenticator(Authenticator&& a) :
- _method(a.method()),
- _auth_fun(
- new detail::auth_fun<Authenticator>(
- std::forward<Authenticator>(a)
- )
- )
- {}
- std::string_view method() const {
- return _method;
- }
- template <typename CompletionToken>
- decltype(auto) async_auth(
- auth_step_e step, std::string data,
- CompletionToken&& token
- ) {
- using Signature = void (error_code, std::string);
- auto initiation = [](
- auto handler, any_authenticator& self,
- auth_step_e step, std::string data
- ) {
- self._auth_fun->async_auth(
- step, std::move(data), std::move(handler)
- );
- };
- return asio::async_initiate<CompletionToken, Signature>(
- initiation, token, std::ref(*this), step, std::move(data)
- );
- }
- };
- } // end namespace boost::mqtt5::detail
- #endif // !BOOST_MQTT5_ANY_AUTHENTICATOR
|