aop_unsubscribe.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef __ASIO2_MQTT_AOP_UNSUBSCRIBE_HPP__
  11. #define __ASIO2_MQTT_AOP_UNSUBSCRIBE_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <asio2/base/iopool.hpp>
  16. #include <asio2/base/detail/function_traits.hpp>
  17. #include <asio2/base/detail/util.hpp>
  18. #include <asio2/mqtt/message.hpp>
  19. namespace asio2::detail
  20. {
  21. template<class caller_t, class args_t>
  22. class mqtt_aop_unsubscribe
  23. {
  24. friend caller_t;
  25. protected:
  26. // must be server
  27. template<class Message, class Response, bool IsClient = args_t::is_client>
  28. inline std::enable_if_t<!IsClient, void>
  29. _before_unsubscribe_callback(
  30. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  31. Message& msg, Response& rep)
  32. {
  33. detail::ignore_unused(ec, caller_ptr, caller, om, msg, rep);
  34. using message_type [[maybe_unused]] = typename detail::remove_cvref_t<Message>;
  35. using response_type [[maybe_unused]] = typename detail::remove_cvref_t<Response>;
  36. rep.packet_id(msg.packet_id());
  37. mqtt::utf8_string_set& topic_filters = msg.topic_filters();
  38. topic_filters.for_each([&](/*mqtt::utf8_string*/auto& str)
  39. {
  40. auto[share_name, topic_filter] = mqtt::parse_topic_filter(str.data_view());
  41. if (!share_name.empty())
  42. {
  43. caller->shared_targets().erase(caller_ptr, share_name, topic_filter);
  44. }
  45. std::size_t removed = caller->subs_map().erase(topic_filter, caller->client_id());
  46. // The Payload contains a list of Reason Codes.
  47. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194
  48. if constexpr (std::is_same_v<response_type, mqtt::v5::unsuback>)
  49. {
  50. if /**/ (topic_filter.empty())
  51. rep.add_reason_codes(detail::to_underlying(mqtt::error::topic_filter_invalid));
  52. else if (removed == 0)
  53. rep.add_reason_codes(detail::to_underlying(mqtt::error::no_subscription_existed));
  54. else
  55. rep.add_reason_codes(detail::to_underlying(mqtt::error::success));
  56. }
  57. else
  58. {
  59. std::ignore = removed;
  60. }
  61. });
  62. }
  63. template<class Message, class Response, bool IsClient = args_t::is_client>
  64. inline std::enable_if_t<IsClient, void>
  65. _before_unsubscribe_callback(
  66. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  67. Message& msg, Response& rep)
  68. {
  69. detail::ignore_unused(ec, caller_ptr, caller, om, msg, rep);
  70. ASIO2_ASSERT(false && "client should't recv the unsubscribe message");
  71. }
  72. // must be server
  73. inline void _before_user_callback_impl(
  74. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  75. mqtt::v3::unsubscribe& msg, mqtt::v3::unsuback& rep)
  76. {
  77. if (_before_unsubscribe_callback(ec, caller_ptr, caller, om, msg, rep); ec)
  78. return;
  79. }
  80. // must be server
  81. inline void _before_user_callback_impl(
  82. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  83. mqtt::v4::unsubscribe& msg, mqtt::v4::unsuback& rep)
  84. {
  85. if (_before_unsubscribe_callback(ec, caller_ptr, caller, om, msg, rep); ec)
  86. return;
  87. }
  88. // must be server
  89. inline void _before_user_callback_impl(
  90. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  91. mqtt::v5::unsubscribe& msg, mqtt::v5::unsuback& rep)
  92. {
  93. if (_before_unsubscribe_callback(ec, caller_ptr, caller, om, msg, rep); ec)
  94. return;
  95. }
  96. inline void _after_user_callback_impl(
  97. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  98. mqtt::v3::unsubscribe& msg, mqtt::v3::unsuback& rep)
  99. {
  100. detail::ignore_unused(ec, caller_ptr, caller, om, msg, rep);
  101. }
  102. inline void _after_user_callback_impl(
  103. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  104. mqtt::v4::unsubscribe& msg, mqtt::v4::unsuback& rep)
  105. {
  106. detail::ignore_unused(ec, caller_ptr, caller, om, msg, rep);
  107. }
  108. inline void _after_user_callback_impl(
  109. error_code& ec, std::shared_ptr<caller_t>& caller_ptr, caller_t* caller, mqtt::message& om,
  110. mqtt::v5::unsubscribe& msg, mqtt::v5::unsuback& rep)
  111. {
  112. detail::ignore_unused(ec, caller_ptr, caller, om, msg, rep);
  113. }
  114. };
  115. }
  116. #endif // !__ASIO2_MQTT_AOP_UNSUBSCRIBE_HPP__