diff --git a/CHANGELOG.md b/CHANGELOG.md index 1705673d..2c2db4e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - The `mqtt::exception` checks if the 'rc' return code actually contains a reason code error, amd if so, sets it as the reason code. - `property` can now report the `typeid` of its contained value. - The `properties` list implements a const iterator +- Added a `to_string()` and `operator<<()` for reason codes. - Completely reformat the sources and added a .clang-format file (a project master and a slightly-different one for headers). - Added GitHub CI Action, removing legacy Travis and Appveyor files diff --git a/examples/async_consume_v5.cpp b/examples/async_consume_v5.cpp index 84a37fba..b4259cdb 100644 --- a/examples/async_consume_v5.cpp +++ b/examples/async_consume_v5.cpp @@ -63,7 +63,8 @@ int main(int argc, char* argv[]) }); cli.set_disconnected_handler([](const mqtt::properties&, mqtt::ReasonCode reason) { - cout << "*** Disconnected. Reason: " << reason << " ***" << endl; + cout << "*** Disconnected. Reason [0x" + << hex << int{reason} << "]: " << reason << " ***" << endl; }); // Start consumer before connecting to make sure to not miss messages @@ -81,7 +82,7 @@ int main(int argc, char* argv[]) // Make sure we were granted a v5 connection. if (rsp.get_mqtt_version() < MQTTVERSION_5) { - cout << "Did not get an MQTT v5 connection." << endl; + cout << "\n Did not get an MQTT v5 connection." << flush; exit(1); } @@ -89,17 +90,17 @@ int main(int argc, char* argv[]) // there is a session, then the server remembers us and our // subscriptions. if (!rsp.is_session_present()) { - cout << "Session not present on broker. Subscribing." << endl; + cout << "\n Session not present on broker. Subscribing..." << flush; cli.subscribe(TOPIC, QOS)->wait(); } - cout << "OK" << endl; + cout << "\n OK" << endl; // Consume messages // This just exits if the client is disconnected. // (See some other examples for auto or manual reconnect) - cout << "Waiting for messages on topic: '" << TOPIC << "'" << endl; + cout << "\nWaiting for messages on topic: '" << TOPIC << "'" << endl; while (true) { auto msg = cli.consume_message(); diff --git a/include/mqtt/CMakeLists.txt b/include/mqtt/CMakeLists.txt index f3f8ab8c..9fc173f2 100644 --- a/include/mqtt/CMakeLists.txt +++ b/include/mqtt/CMakeLists.txt @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2016-2024 +# Copyright (c) 2016-2024 Frank Pagliughi # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v2.0 @@ -34,6 +34,7 @@ install( message.h platform.h properties.h + reason_code.h response_options.h server_response.h ssl_options.h diff --git a/include/mqtt/reason_code.h b/include/mqtt/reason_code.h new file mode 100644 index 00000000..fe55ec3b --- /dev/null +++ b/include/mqtt/reason_code.h @@ -0,0 +1,110 @@ +///////////////////////////////////////////////////////////////////////////// +/// @file reason_code.h +/// +/// MQTT v5 reason codes for the Paho MQTT C++ library. +/// +/// @date July 5, 2024 +/// @author Frank Pagliughi +///////////////////////////////////////////////////////////////////////////// + +/******************************************************************************* + * Copyright (c) 2024 Frank Pagliughi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v20.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Frank Pagliughi - initial implementation and documentation + *******************************************************************************/ + +#ifndef __reason_code_h +#define __reason_code_h + +#include +#include + +namespace mqtt { + +///////////////////////////////////////////////////////////////////////////// + +/** + * The MQTT v5 Reason Codes. + */ +enum ReasonCode { + SUCCESS = 0, + NORMAL_DISCONNECTION = 0, + GRANTED_QOS_0 = 0, + GRANTED_QOS_1 = 1, + GRANTED_QOS_2 = 2, + DISCONNECT_WITH_WILL_MESSAGE = 4, + NO_MATCHING_SUBSCRIBERS = 16, + NO_SUBSCRIPTION_FOUND = 17, + CONTINUE_AUTHENTICATION = 24, + RE_AUTHENTICATE = 25, + UNSPECIFIED_ERROR = 128, + MALFORMED_PACKET = 129, + PROTOCOL_ERROR = 130, + IMPLEMENTATION_SPECIFIC_ERROR = 131, + UNSUPPORTED_PROTOCOL_VERSION = 132, + CLIENT_IDENTIFIER_NOT_VALID = 133, + BAD_USER_NAME_OR_PASSWORD = 134, + NOT_AUTHORIZED = 135, + SERVER_UNAVAILABLE = 136, + SERVER_BUSY = 137, + BANNED = 138, + SERVER_SHUTTING_DOWN = 139, + BAD_AUTHENTICATION_METHOD = 140, + KEEP_ALIVE_TIMEOUT = 141, + SESSION_TAKEN_OVER = 142, + TOPIC_FILTER_INVALID = 143, + TOPIC_NAME_INVALID = 144, + PACKET_IDENTIFIER_IN_USE = 145, + PACKET_IDENTIFIER_NOT_FOUND = 146, + RECEIVE_MAXIMUM_EXCEEDED = 147, + TOPIC_ALIAS_INVALID = 148, + PACKET_TOO_LARGE = 149, + MESSAGE_RATE_TOO_HIGH = 150, + QUOTA_EXCEEDED = 151, + ADMINISTRATIVE_ACTION = 152, + PAYLOAD_FORMAT_INVALID = 153, + RETAIN_NOT_SUPPORTED = 154, + QOS_NOT_SUPPORTED = 155, + USE_ANOTHER_SERVER = 156, + SERVER_MOVED = 157, + SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158, + CONNECTION_RATE_EXCEEDED = 159, + MAXIMUM_CONNECT_TIME = 160, + SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161, + WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162, + // This is not a protocol code; used internally by the library (obsolete) + MQTTPP_V3_CODE = 0 +}; + +/** + * Get the string representation of the reason code. + * + * @param reasonCode An MQTT v5 reason code. + * @return The string representation of the reason code. + */ +std::string to_string(ReasonCode reasonCode); + +/** + * ostream inserter for reason codes + * + * @param os The output stream + * @param reasonCode The reason code. + * + * @return Reference to the output stream + */ +std::ostream& operator<<(std::ostream& os, ReasonCode reasonCode); + +///////////////////////////////////////////////////////////////////////////// +} // namespace mqtt + +#endif // __reason_code_h diff --git a/include/mqtt/types.h b/include/mqtt/types.h index 14ec6c42..23f62a1d 100644 --- a/include/mqtt/types.h +++ b/include/mqtt/types.h @@ -28,6 +28,9 @@ #include #include +// Pull in reason codes here for backward compatability with old version +#include "mqtt/reason_code.h" + namespace mqtt { ///////////////////////////////////////////////////////////////////////////// @@ -46,62 +49,6 @@ using string_ptr = std::shared_ptr; /** Smart/shared pointer to a const binary blob */ using binary_ptr = std::shared_ptr; -///////////////////////////////////////////////////////////////////////////// -// General protocol enumerations - -/** - * The MQTT v5 Reason Codes. - */ -enum ReasonCode { - SUCCESS = 0, - NORMAL_DISCONNECTION = 0, - GRANTED_QOS_0 = 0, - GRANTED_QOS_1 = 1, - GRANTED_QOS_2 = 2, - DISCONNECT_WITH_WILL_MESSAGE = 4, - NO_MATCHING_SUBSCRIBERS = 16, - NO_SUBSCRIPTION_FOUND = 17, - CONTINUE_AUTHENTICATION = 24, - RE_AUTHENTICATE = 25, - UNSPECIFIED_ERROR = 128, - MALFORMED_PACKET = 129, - PROTOCOL_ERROR = 130, - IMPLEMENTATION_SPECIFIC_ERROR = 131, - UNSUPPORTED_PROTOCOL_VERSION = 132, - CLIENT_IDENTIFIER_NOT_VALID = 133, - BAD_USER_NAME_OR_PASSWORD = 134, - NOT_AUTHORIZED = 135, - SERVER_UNAVAILABLE = 136, - SERVER_BUSY = 137, - BANNED = 138, - SERVER_SHUTTING_DOWN = 139, - BAD_AUTHENTICATION_METHOD = 140, - KEEP_ALIVE_TIMEOUT = 141, - SESSION_TAKEN_OVER = 142, - TOPIC_FILTER_INVALID = 143, - TOPIC_NAME_INVALID = 144, - PACKET_IDENTIFIER_IN_USE = 145, - PACKET_IDENTIFIER_NOT_FOUND = 146, - RECEIVE_MAXIMUM_EXCEEDED = 147, - TOPIC_ALIAS_INVALID = 148, - PACKET_TOO_LARGE = 149, - MESSAGE_RATE_TOO_HIGH = 150, - QUOTA_EXCEEDED = 151, - ADMINISTRATIVE_ACTION = 152, - PAYLOAD_FORMAT_INVALID = 153, - RETAIN_NOT_SUPPORTED = 154, - QOS_NOT_SUPPORTED = 155, - USE_ANOTHER_SERVER = 156, - SERVER_MOVED = 157, - SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158, - CONNECTION_RATE_EXCEEDED = 159, - MAXIMUM_CONNECT_TIME = 160, - SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161, - WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162, - // This is not a protocol code; used internally by the library (obsolete) - MQTTPP_V3_CODE = 0 -}; - ///////////////////////////////////////////////////////////////////////////// // Time functions diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 35075b9a..2ecc70bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ set(COMMON_SRC iclient_persistence.cpp message.cpp properties.cpp + reason_code.cpp response_options.cpp server_response.cpp ssl_options.cpp diff --git a/src/properties.cpp b/src/properties.cpp index 262ea670..13d0dc51 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -271,5 +271,4 @@ property properties::get(property::code propid, size_t idx /*=0*/) } ///////////////////////////////////////////////////////////////////////////// -// end namespace 'mqtt' } // namespace mqtt diff --git a/src/reason_code.cpp b/src/reason_code.cpp new file mode 100644 index 00000000..78bf927c --- /dev/null +++ b/src/reason_code.cpp @@ -0,0 +1,38 @@ +// reason_code.cpp + +/******************************************************************************* + * Copyright (c) 2024 Frank Pagliughi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v20.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Frank Pagliughi - initial implementation and documentation + *******************************************************************************/ + +#include "mqtt/properties.h" + +namespace mqtt { + +///////////////////////////////////////////////////////////////////////////// + + +std::string to_string(ReasonCode reasonCode) +{ + return std::string{MQTTReasonCode_toString(MQTTReasonCodes(reasonCode))}; +} + +std::ostream& operator<<(std::ostream& os, ReasonCode reasonCode) +{ + os << MQTTReasonCode_toString(MQTTReasonCodes(reasonCode)); + return os; +} + +///////////////////////////////////////////////////////////////////////////// +} // namespace mqtt