File indexing completed on 2025-09-17 08:38:19
0001
0002
0003
0004
0005
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 }
0140
0141
0142 #endif