Back to home page

EIC code displayed by LXR

 
 

    


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

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_REASON_CODES_HPP
0009 #define BOOST_MQTT5_REASON_CODES_HPP
0010 
0011 #include <algorithm>
0012 #include <cstdint>
0013 #include <optional>
0014 #include <ostream>
0015 #include <type_traits>
0016 #include <utility>
0017 
0018 namespace boost::mqtt5 {
0019 
0020 /// \cond internal
0021 namespace reason_codes {
0022 
0023 enum class category : uint8_t {
0024     none,
0025     connack, puback, pubrec,
0026     pubrel, pubcomp, suback,
0027     unsuback, auth, disconnect
0028 };
0029 
0030 } // end namespace reason_codes
0031 
0032 /// \endcond
0033 
0034 /**
0035  * \brief A class holding Reason Code values originating from Control Packets.
0036  *
0037  * \details A Reason Code is a one byte unsigned value that indicates the result of an operation.
0038  *    Reason Codes less than 0x80 indicate successful completion of an operation.
0039  *    The normal Reason Code for success is 0.
0040  *    Reason Code values of 0x80 or greater indicate failure.
0041  *    The \__CONNACK\__,  \__PUBACK\__,  \__PUBREC\__,  \__PUBREL\__,  \__PUBCOMP\__,  \__DISCONNECT\__
0042  *    and  \__AUTH\__ Control Packets have a single Reason Code as part of the Variable Header.
0043  *    The \__SUBACK\__ and \__UNSUBACK\__ packets contain a list of one or more Reason Codes in the Payload.
0044  *
0045  *    \see See \__REASON_CODES\__ for a complete list of all possible instances of this class.
0046  */
0047 class reason_code {
0048     uint8_t _code;
0049     reason_codes::category _category { reason_codes::category::none };
0050 public:
0051 /// \cond internal
0052     constexpr reason_code() : _code(0xff) {}
0053 
0054     constexpr reason_code(uint8_t code, reason_codes::category cat) :
0055         _code(code), _category(cat)
0056     {}
0057 
0058     constexpr explicit reason_code(uint8_t code) : _code(code) {}
0059 /// \endcond
0060 
0061     /**
0062      * \brief Indication if the object holds a Reason Code indicating an error.
0063      *
0064      * \details Any Reason Code holding a value equal to or greater than 0x80.
0065      */
0066     explicit operator bool() const noexcept {
0067         return _code >= 0x80;
0068     }
0069 
0070     /**
0071      * \brief Returns the byte value of the Reason Code.
0072      */
0073     constexpr uint8_t value() const noexcept {
0074         return _code;
0075     }
0076 
0077     /// Insertion operator.
0078     friend std::ostream& operator<<(std::ostream& os, const reason_code& rc) {
0079         os << rc.message();
0080         return os;
0081     }
0082 
0083     /// Operator less than.
0084     friend bool operator<(const reason_code& lhs, const reason_code& rhs) {
0085         return lhs._code < rhs._code;
0086     }
0087 
0088     /// Equality operator.
0089     friend bool operator==(const reason_code& lhs, const reason_code& rhs) {
0090         return lhs._code == rhs._code && lhs._category == rhs._category;
0091     }
0092 
0093     /**
0094      * \brief Returns a message describing the meaning behind the Reason Code.
0095      */
0096     std::string message() const {
0097         switch (_code) {
0098             case 0x00:
0099                 if (_category == reason_codes::category::suback)
0100                     return "The subscription is accepted with maximum QoS sent at 0";
0101                 if (_category == reason_codes::category::disconnect)
0102                     return "Close the connection normally. Do not send the Will Message";
0103                 return "The operation completed successfully";
0104             case 0x01:
0105                 return "The subscription is accepted with maximum QoS sent at 1";
0106             case 0x02:
0107                 return "The subscription is accepted with maximum QoS sent at 2";
0108             case 0x04:
0109                 return "The Client wishes to disconnect but requires"
0110                         "that the Server also publishes its Will Message";
0111             case 0x10:
0112                 return "The message is accepted but there are no subscribers";
0113             case 0x11:
0114                 return "No matching Topic Filter is being used by the Client.";
0115             case 0x18:
0116                 return "Continue the authentication with another step";
0117             case 0x19:
0118                 return "Initiate a re-authentication";
0119             case 0x80:
0120                 return "The Server does not wish to reveal the reason for the"
0121                         "failure or none of the other Reason Codes apply";
0122             case 0x81:
0123                 return "Data within the packet could not be correctly parsed";
0124             case 0x82:
0125                 return "Data in the packet does not conform to this specification";
0126             case 0x83:
0127                 return "The packet is valid but not accepted by this Server";
0128             case 0x84:
0129                 return "The Server does not support the requested "
0130                         "version of the MQTT protocol";
0131             case 0x85:
0132                 return "The Client ID is valid but not allowed by this Server";
0133             case 0x86:
0134                 return "The Server does not accept the User Name or Password provided";
0135             case 0x87:
0136                 return "The request is not authorized";
0137             case 0x88:
0138                 return "The MQTT Server is not available";
0139             case 0x89:
0140                 return "The MQTT Server is busy, try again later";
0141             case 0x8a:
0142                 return "The Client has been banned by administrative action";
0143             case 0x8b:
0144                 return "The Server is shutting down";
0145             case 0x8c:
0146                 return "The authentication method is not supported or "
0147                         "does not match the method currently in use";
0148             case 0x8d:
0149                 return "No packet has been received for 1.5 times the Keepalive time";
0150             case 0x8e:
0151                 return "Another Connection using the same ClientID has connected "
0152                         "causing this Connection to be closed";
0153             case 0x8f:
0154                 return "The Topic Filer is not malformed, but it is not accepted";
0155             case 0x90:
0156                 return "The Topic Name is not malformed, but it is not accepted";
0157             case 0x91:
0158                 return "The Packet Identifier is already in use";
0159             case 0x92:
0160                 return "The Packet Identifier is not known";
0161             case 0x93:
0162                 return "The Client or Server has received more than the Receive "
0163                         "Maximum publication for which it has not sent PUBACK or PUBCOMP";
0164             case 0x94:
0165                 return "The Client or Server received a PUBLISH packet containing "
0166                         "a Topic Alias greater than the Maximum Topic Alias";
0167             case 0x95:
0168                 return "The packet exceeded the maximum permissible size";
0169             case 0x96:
0170                 return "The received data rate is too high";
0171             case 0x97:
0172                 return "An implementation or administrative imposed limit has been exceeded";
0173             case 0x98:
0174                 return "The Connection is closed due to an administrative action";
0175             case 0x99:
0176                 return "The Payload does not match the specified Payload Format Indicator";
0177             case 0x9a:
0178                 return "The Server does not support retained messages";
0179             case 0x9b:
0180                 return "The Server does not support the QoS the Client specified or "
0181                         "it is greater than the Maximum QoS specified";
0182             case 0x9c:
0183                 return "The Client should temporarily use another server";
0184             case 0x9d:
0185                 return "The Client should permanently use another server";
0186             case 0x9e:
0187                 return "The Server does not support Shared Subscriptions for this Client";
0188             case 0x9f:
0189                 return "The connection rate limit has been exceeded";
0190             case 0xa0:
0191                 return "The maximum connection time authorized for this "
0192                         "connection has been exceeded";
0193             case 0xa1:
0194                 return "The Server does not support Subscription Identifiers";
0195             case 0xa2:
0196                 return "The Server does not support Wildcard Subscriptions";
0197             case 0xff:
0198                 return "No reason code";
0199             default:
0200                 return "Invalid reason code";
0201         }
0202     }
0203 };
0204 
0205 namespace reason_codes {
0206 
0207 /** \brief  No Reason Code. A \ref client::error occurred.*/
0208 constexpr reason_code empty {};
0209 
0210 /** \brief The operation completed successfully. */
0211 constexpr reason_code success { 0x00 };
0212 
0213 /** \brief Close the connection normally. Do not send the Will Message. */
0214 constexpr reason_code normal_disconnection { 0x00, category::disconnect };
0215 
0216 /** \brief The subscription is accepted with maximum QoS sent at 0. */
0217 constexpr reason_code granted_qos_0 { 0x00, category::suback };
0218 
0219 /** \brief The subscription is accepted with maximum QoS sent at 1. */
0220 constexpr reason_code granted_qos_1 { 0x01 };
0221 
0222 /** \brief The subscription is accepted with maximum QoS sent at 2 */
0223 constexpr reason_code granted_qos_2 { 0x02 };
0224 
0225 /** \brief The Client wishes to disconnect but requires that
0226  the Server also publishes its Will Message. */
0227 constexpr reason_code disconnect_with_will_message { 0x04 };
0228 
0229 /** \brief The message is accepted but there are no subscribers. */
0230 constexpr reason_code no_matching_subscribers { 0x10 };
0231 
0232 /** \brief No matching Topic Filter is being used by the Client. */
0233 constexpr reason_code no_subscription_existed { 0x11 };
0234 
0235 /** \brief Continue the authentication with another step. */
0236 constexpr reason_code continue_authentication { 0x18 };
0237 
0238 /** \brief Initiate a re-authentication. */
0239 constexpr reason_code reauthenticate { 0x19 };
0240 
0241 /** \brief The Server does not wish to reveal the reason for the
0242  failure or none of the other Reason Codes apply. */
0243 constexpr reason_code unspecified_error { 0x80 };
0244 
0245 /** \brief Data within the packet could not be correctly parsed. */
0246 constexpr reason_code malformed_packet { 0x81 };
0247 
0248 /** \brief Data in the packet does not conform to this specification. */
0249 constexpr reason_code protocol_error { 0x82 };
0250 
0251 /** \brief The packet is valid but not accepted by this Server. */
0252 constexpr reason_code implementation_specific_error { 0x83 };
0253 
0254 /** \brief The Server does not support the requested version of the MQTT protocol. */
0255 constexpr reason_code unsupported_protocol_version { 0x84 };
0256 
0257 /** \brief The Client ID is valid but not allowed by this Server. */
0258 constexpr reason_code client_identifier_not_valid { 0x85 };
0259 
0260 /** \brief The Server does not accept the User Name or Password provided. */
0261 constexpr reason_code bad_username_or_password { 0x86 };
0262 
0263 /** \brief The request is not authorized. */
0264 constexpr reason_code not_authorized { 0x87 };
0265 
0266 /** \brief The MQTT Server is not available. */
0267 constexpr reason_code server_unavailable { 0x88 };
0268 
0269 /** \brief The MQTT Server is busy, try again later. */
0270 constexpr reason_code server_busy { 0x89 };
0271 
0272 /** \brief The Client has been banned by administrative action. */
0273 constexpr reason_code banned { 0x8a };
0274 
0275 /** \brief The Server is shutting down. */
0276 constexpr reason_code server_shutting_down { 0x8b };
0277 
0278 /** \brief The authentication method is not supported or
0279  does not match the method currently in use. */
0280 constexpr reason_code bad_authentication_method { 0x8c };
0281 
0282 /** \brief No packet has been received for 1.5 times the Keepalive time. */
0283 constexpr reason_code keep_alive_timeout { 0x8d };
0284 
0285 /** \brief Another Connection using the same ClientID has connected
0286  causing this Connection to be closed. */
0287 constexpr reason_code session_taken_over { 0x8e };
0288 
0289 /** \brief The Topic Filter is not malformed, but it is not accepted. */
0290 constexpr reason_code topic_filter_invalid { 0x8f };
0291 
0292 /** \brief The Topic Name is not malformed, but it is not accepted. */
0293 constexpr reason_code topic_name_invalid { 0x90 };
0294 
0295 /** \brief The Packet Identifier is already in use. */
0296 constexpr reason_code packet_identifier_in_use { 0x91 };
0297 
0298 /** \brief The Packet Identifier is not known. */
0299 constexpr reason_code packet_identifier_not_found { 0x92 };
0300 
0301 /** \brief The Client or Server has received more than the Receive
0302  Maximum publication for which it has not sent PUBACK or PUBCOMP. */
0303 constexpr reason_code receive_maximum_exceeded { 0x93 };
0304 
0305 /** \brief The Client or Server received a PUBLISH packet containing
0306  a Topic Alias greater than the Maximum Topic Alias. */
0307 constexpr reason_code topic_alias_invalid { 0x94 };
0308 
0309 /** \brief The packet exceeded the maximum permissible size. */
0310 constexpr reason_code packet_too_large { 0x95 };
0311 
0312 /** \brief The received data rate is too high. */
0313 constexpr reason_code message_rate_too_high { 0x96 };
0314 
0315 /** \brief An implementation or administrative imposed limit has been exceeded. */
0316 constexpr reason_code quota_exceeded { 0x97 };
0317 
0318 /** \brief The Connection is closed due to an administrative action. */
0319 constexpr reason_code administrative_action { 0x98 };
0320 
0321 /** \brief The Payload does not match the specified Payload Format Indicator. */
0322 constexpr reason_code payload_format_invalid { 0x99 };
0323 
0324 /** \brief The Server does not support retained messages. */
0325 constexpr reason_code retain_not_supported { 0x9a };
0326 
0327 /** \brief The Server does not support the QoS the Client specified or
0328  it is greater than the Maximum QoS specified. */
0329 constexpr reason_code qos_not_supported { 0x9b };
0330 
0331 /** \brief The Client should temporarily use another server. */
0332 constexpr reason_code use_another_server { 0x9c };
0333 
0334 /** \brief The Client should permanently use another server. */
0335 constexpr reason_code server_moved { 0x9d };
0336 
0337 /** \brief The Server does not support Shared Subscriptions for this Client. */
0338 constexpr reason_code shared_subscriptions_not_supported { 0x9e };
0339 
0340 /** \brief The connection rate limit has been exceeded. */
0341 constexpr reason_code connection_rate_exceeded { 0x9f };
0342 
0343 /** \brief The maximum connection time authorized for this
0344  connection has been exceeded. */
0345 constexpr reason_code maximum_connect_time { 0xa0 };
0346 
0347 /** \brief The Server does not support Subscription Identifiers. */
0348 constexpr reason_code subscription_ids_not_supported { 0xa1 };
0349 
0350 /** \brief The Server does not support Wildcard Subscriptions. */
0351 constexpr reason_code wildcard_subscriptions_not_supported { 0xa2 };
0352 
0353 namespace detail {
0354 
0355 template <
0356     category cat,
0357     std::enable_if_t<cat == category::connack, bool> = true
0358 >
0359 std::pair<reason_code*, size_t> valid_codes() {
0360     static reason_code valid_codes[] = {
0361         success, unspecified_error, malformed_packet,
0362         protocol_error, implementation_specific_error,
0363         unsupported_protocol_version, client_identifier_not_valid,
0364         bad_username_or_password, not_authorized,
0365         server_unavailable, server_busy, banned,
0366         bad_authentication_method, topic_name_invalid,
0367         packet_too_large, quota_exceeded,
0368         payload_format_invalid, retain_not_supported,
0369         qos_not_supported, use_another_server,
0370         server_moved, connection_rate_exceeded
0371     };
0372     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0373     return std::make_pair(valid_codes, len);
0374 }
0375 
0376 template <
0377     category cat,
0378     std::enable_if_t<cat == category::auth, bool> = true
0379 >
0380 std::pair<reason_code*, size_t> valid_codes() {
0381     static reason_code valid_codes[] = {
0382         success, continue_authentication, reauthenticate
0383     };
0384     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0385     return std::make_pair(valid_codes, len);
0386 }
0387 
0388 template <
0389     category cat,
0390     std::enable_if_t<
0391         cat == category::puback || cat == category::pubrec, bool
0392     > = true
0393 >
0394 std::pair<reason_code*, size_t> valid_codes() {
0395     static reason_code valid_codes[] = {
0396         success, no_matching_subscribers, unspecified_error,
0397         implementation_specific_error, not_authorized,
0398         topic_name_invalid, packet_identifier_in_use,
0399         quota_exceeded, payload_format_invalid
0400     };
0401     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0402     return std::make_pair(valid_codes, len);
0403 }
0404 
0405 template <
0406     category cat,
0407     std::enable_if_t<
0408         cat == category::pubrel || cat == category::pubcomp, bool
0409     > = true
0410 >
0411 std::pair<reason_code*, size_t> valid_codes() {
0412     static reason_code valid_codes[] = {
0413         success, packet_identifier_not_found
0414     };
0415     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0416     return std::make_pair(valid_codes, len);
0417 }
0418 
0419 template <
0420     category cat,
0421     std::enable_if_t<cat == category::suback, bool> = true
0422 >
0423 std::pair<reason_code*, size_t> valid_codes() {
0424     static reason_code valid_codes[] = {
0425         granted_qos_0, granted_qos_1, granted_qos_2,
0426         unspecified_error, implementation_specific_error,
0427         not_authorized, topic_filter_invalid,
0428         packet_identifier_in_use, quota_exceeded,
0429         shared_subscriptions_not_supported,
0430         subscription_ids_not_supported,
0431         wildcard_subscriptions_not_supported
0432     };
0433     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0434     return std::make_pair(valid_codes, len);
0435 }
0436 
0437 template <
0438     category cat,
0439     std::enable_if_t<cat == category::unsuback, bool> = true
0440 >
0441 std::pair<reason_code*, size_t> valid_codes() {
0442     static reason_code valid_codes[] = {
0443         success, no_subscription_existed,
0444         unspecified_error, implementation_specific_error,
0445         not_authorized, topic_filter_invalid,
0446         packet_identifier_in_use
0447     };
0448     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0449     return std::make_pair(valid_codes, len);
0450 }
0451 
0452 template <
0453     category cat,
0454     std::enable_if_t<cat == category::disconnect, bool> = true
0455 >
0456 std::pair<reason_code*, size_t> valid_codes() {
0457     static reason_code valid_codes[] = {
0458         normal_disconnection, unspecified_error,
0459         malformed_packet, protocol_error,
0460         implementation_specific_error, not_authorized,
0461         server_busy, server_shutting_down,
0462         keep_alive_timeout, session_taken_over,
0463         topic_filter_invalid, topic_name_invalid,
0464         receive_maximum_exceeded, topic_alias_invalid,
0465         packet_too_large, message_rate_too_high,
0466         quota_exceeded, administrative_action,
0467         payload_format_invalid, retain_not_supported,
0468         qos_not_supported, use_another_server,
0469         server_moved, shared_subscriptions_not_supported,
0470         connection_rate_exceeded, maximum_connect_time,
0471         subscription_ids_not_supported,
0472         wildcard_subscriptions_not_supported
0473     };
0474     static size_t len = sizeof(valid_codes) / sizeof(reason_code);
0475     return std::make_pair(valid_codes, len);
0476 }
0477 
0478 
0479 } // end namespace detail
0480 } // end namespace reason_codes
0481 
0482 
0483 template <reason_codes::category cat>
0484 std::optional<reason_code> to_reason_code(uint8_t code) {
0485     auto [ptr, len] = reason_codes::detail::valid_codes<cat>();
0486     auto it = std::lower_bound(ptr, ptr + len, reason_code(code));
0487 
0488     if (it->value() == code)
0489         return *it;
0490     return std::nullopt;
0491 }
0492 
0493 } // end namespace boost::mqtt5
0494 
0495 #endif // !BOOST_MQTT5_REASON_CODES_HPP