Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:38:19

0001 //
0002 // Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MQTT5_ANY_AUTHENTICATOR
0009 #define BOOST_MQTT5_ANY_AUTHENTICATOR
0010 
0011 #include <boost/mqtt5/types.hpp>
0012 
0013 #include <boost/asio/any_completion_handler.hpp>
0014 #include <boost/asio/async_result.hpp>
0015 #include <boost/system/error_code.hpp>
0016 #include <boost/type_traits/is_detected.hpp>
0017 #include <boost/type_traits/is_detected_convertible.hpp>
0018 
0019 #include <memory>
0020 #include <string>
0021 #include <string_view>
0022 #include <type_traits>
0023 
0024 namespace boost::mqtt5::detail {
0025 
0026 namespace asio = boost::asio;
0027 using error_code = boost::system::error_code;
0028 
0029 using auth_handler_type = asio::any_completion_handler<
0030     void (error_code, std::string)
0031 >;
0032 
0033 template <typename T, typename ...Ts>
0034 using async_auth_sig = decltype(
0035     std::declval<T>().async_auth(std::declval<Ts>()...)
0036 );
0037 
0038 template <typename T>
0039 using method_sig = decltype(
0040     std::declval<T>().method()
0041 );
0042 
0043 template <typename T>
0044 constexpr bool is_authenticator =
0045     boost::is_detected<
0046         async_auth_sig, T,
0047         auth_step_e, std::string, auth_handler_type
0048     >::value &&
0049     boost::is_detected_convertible_v<std::string_view, method_sig, T>;
0050 
0051 class auth_fun_base {
0052     using auth_func = void(*)(
0053         auth_step_e, std::string, auth_handler_type, auth_fun_base*
0054     );
0055     auth_func _auth_func;
0056 
0057 public:
0058     auth_fun_base(auth_func f) : _auth_func(f) {}
0059     ~auth_fun_base() = default;
0060 
0061     void async_auth(
0062         auth_step_e step, std::string data,
0063         auth_handler_type auth_handler
0064     ) {
0065         _auth_func(step, std::move(data), std::move(auth_handler), this);
0066     }
0067 };
0068 
0069 template <
0070     typename Authenticator,
0071     typename = std::enable_if_t<is_authenticator<Authenticator>>
0072 >
0073 class auth_fun : public auth_fun_base {
0074     Authenticator _authenticator;
0075 
0076 public:
0077     auth_fun(Authenticator authenticator) :
0078         auth_fun_base(&async_auth),
0079         _authenticator(std::forward<Authenticator>(authenticator))
0080     {}
0081 
0082     static void async_auth(
0083         auth_step_e step, std::string data, auth_handler_type auth_handler,
0084         auth_fun_base* base_ptr
0085     ) {
0086         auto auth_fun_ptr = static_cast<auth_fun*>(base_ptr);
0087         auth_fun_ptr->_authenticator.async_auth(
0088             step, std::move(data), std::move(auth_handler)
0089         );
0090     }
0091 };
0092 
0093 class any_authenticator {
0094     std::string _method;
0095     std::shared_ptr<detail::auth_fun_base> _auth_fun;
0096 
0097 public:
0098     any_authenticator() = default;
0099 
0100     template <
0101         typename Authenticator,
0102         std::enable_if_t<detail::is_authenticator<Authenticator>, bool> = true
0103     >
0104     any_authenticator(Authenticator&& a) :
0105         _method(a.method()),
0106         _auth_fun(
0107             new detail::auth_fun<Authenticator>(
0108                 std::forward<Authenticator>(a)
0109             )
0110         )
0111     {}
0112 
0113     std::string_view method() const {
0114         return _method;
0115     }
0116 
0117     template <typename CompletionToken>
0118     decltype(auto) async_auth(
0119         auth_step_e step, std::string data,
0120         CompletionToken&& token
0121     ) {
0122         using Signature = void (error_code, std::string);
0123 
0124         auto initiation = [](
0125             auto handler, any_authenticator& self,
0126             auth_step_e step, std::string data
0127         ) {
0128             self._auth_fun->async_auth(
0129                 step, std::move(data), std::move(handler)
0130             );
0131         };
0132 
0133         return asio::async_initiate<CompletionToken, Signature>(
0134             initiation, token, std::ref(*this), step, std::move(data)
0135         );
0136     }
0137 };
0138 
0139 } // end namespace boost::mqtt5::detail
0140 
0141 
0142 #endif // !BOOST_MQTT5_ANY_AUTHENTICATOR