File indexing completed on 2025-09-17 08:38:23
0001
0002
0003
0004
0005
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
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 }
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 class reason_code {
0048 uint8_t _code;
0049 reason_codes::category _category { reason_codes::category::none };
0050 public:
0051
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
0060
0061
0062
0063
0064
0065
0066 explicit operator bool() const noexcept {
0067 return _code >= 0x80;
0068 }
0069
0070
0071
0072
0073 constexpr uint8_t value() const noexcept {
0074 return _code;
0075 }
0076
0077
0078 friend std::ostream& operator<<(std::ostream& os, const reason_code& rc) {
0079 os << rc.message();
0080 return os;
0081 }
0082
0083
0084 friend bool operator<(const reason_code& lhs, const reason_code& rhs) {
0085 return lhs._code < rhs._code;
0086 }
0087
0088
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
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
0208 constexpr reason_code empty {};
0209
0210
0211 constexpr reason_code success { 0x00 };
0212
0213
0214 constexpr reason_code normal_disconnection { 0x00, category::disconnect };
0215
0216
0217 constexpr reason_code granted_qos_0 { 0x00, category::suback };
0218
0219
0220 constexpr reason_code granted_qos_1 { 0x01 };
0221
0222
0223 constexpr reason_code granted_qos_2 { 0x02 };
0224
0225
0226
0227 constexpr reason_code disconnect_with_will_message { 0x04 };
0228
0229
0230 constexpr reason_code no_matching_subscribers { 0x10 };
0231
0232
0233 constexpr reason_code no_subscription_existed { 0x11 };
0234
0235
0236 constexpr reason_code continue_authentication { 0x18 };
0237
0238
0239 constexpr reason_code reauthenticate { 0x19 };
0240
0241
0242
0243 constexpr reason_code unspecified_error { 0x80 };
0244
0245
0246 constexpr reason_code malformed_packet { 0x81 };
0247
0248
0249 constexpr reason_code protocol_error { 0x82 };
0250
0251
0252 constexpr reason_code implementation_specific_error { 0x83 };
0253
0254
0255 constexpr reason_code unsupported_protocol_version { 0x84 };
0256
0257
0258 constexpr reason_code client_identifier_not_valid { 0x85 };
0259
0260
0261 constexpr reason_code bad_username_or_password { 0x86 };
0262
0263
0264 constexpr reason_code not_authorized { 0x87 };
0265
0266
0267 constexpr reason_code server_unavailable { 0x88 };
0268
0269
0270 constexpr reason_code server_busy { 0x89 };
0271
0272
0273 constexpr reason_code banned { 0x8a };
0274
0275
0276 constexpr reason_code server_shutting_down { 0x8b };
0277
0278
0279
0280 constexpr reason_code bad_authentication_method { 0x8c };
0281
0282
0283 constexpr reason_code keep_alive_timeout { 0x8d };
0284
0285
0286
0287 constexpr reason_code session_taken_over { 0x8e };
0288
0289
0290 constexpr reason_code topic_filter_invalid { 0x8f };
0291
0292
0293 constexpr reason_code topic_name_invalid { 0x90 };
0294
0295
0296 constexpr reason_code packet_identifier_in_use { 0x91 };
0297
0298
0299 constexpr reason_code packet_identifier_not_found { 0x92 };
0300
0301
0302
0303 constexpr reason_code receive_maximum_exceeded { 0x93 };
0304
0305
0306
0307 constexpr reason_code topic_alias_invalid { 0x94 };
0308
0309
0310 constexpr reason_code packet_too_large { 0x95 };
0311
0312
0313 constexpr reason_code message_rate_too_high { 0x96 };
0314
0315
0316 constexpr reason_code quota_exceeded { 0x97 };
0317
0318
0319 constexpr reason_code administrative_action { 0x98 };
0320
0321
0322 constexpr reason_code payload_format_invalid { 0x99 };
0323
0324
0325 constexpr reason_code retain_not_supported { 0x9a };
0326
0327
0328
0329 constexpr reason_code qos_not_supported { 0x9b };
0330
0331
0332 constexpr reason_code use_another_server { 0x9c };
0333
0334
0335 constexpr reason_code server_moved { 0x9d };
0336
0337
0338 constexpr reason_code shared_subscriptions_not_supported { 0x9e };
0339
0340
0341 constexpr reason_code connection_rate_exceeded { 0x9f };
0342
0343
0344
0345 constexpr reason_code maximum_connect_time { 0xa0 };
0346
0347
0348 constexpr reason_code subscription_ids_not_supported { 0xa1 };
0349
0350
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 }
0480 }
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 }
0494
0495 #endif