From 22f1330fed3eefca4e76b4dfb079358b47808ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korina=20=C5=A0imi=C4=8Devi=C4=87?= Date: Mon, 16 Oct 2023 15:57:26 +0200 Subject: [PATCH] [mqtt-client] reason codes & properties documented Summary: related to T12804 Reviewers: ivica Reviewed By: ivica Subscribers: miljen Differential Revision: https://repo.mireo.local/D26113 --- doc/Jamfile | 4 +- doc/qbk/00_main.qbk | 31 ++- doc/qbk/helpers/Reason_codes.qbk | 114 --------- .../ExecutionContext.qbk | 2 +- doc/qbk/{helpers => reference}/StreamType.qbk | 4 +- doc/qbk/{helpers => reference}/TlsContext.qbk | 2 +- doc/qbk/reference/properties/Properties.qbk | 151 ++++++++++++ doc/qbk/{helpers => reference}/quickref.xml | 4 + .../reference/reason_codes/Reason_codes.qbk | 16 ++ .../reason_codes}/rcref.xml | 56 ++--- example/tcp.cpp | 2 +- include/async_mqtt5/error.hpp | 223 +++++++++++++----- include/async_mqtt5/mqtt_client.hpp | 15 +- include/async_mqtt5/property_types.hpp | 54 ++--- include/async_mqtt5/types.hpp | 87 +++++-- 15 files changed, 497 insertions(+), 268 deletions(-) delete mode 100644 doc/qbk/helpers/Reason_codes.qbk rename doc/qbk/{helpers => reference}/ExecutionContext.qbk (98%) rename doc/qbk/{helpers => reference}/StreamType.qbk (90%) rename doc/qbk/{helpers => reference}/TlsContext.qbk (97%) create mode 100644 doc/qbk/reference/properties/Properties.qbk rename doc/qbk/{helpers => reference}/quickref.xml (93%) create mode 100644 doc/qbk/reference/reason_codes/Reason_codes.qbk rename doc/qbk/{helpers => reference/reason_codes}/rcref.xml (95%) diff --git a/doc/Jamfile b/doc/Jamfile index 3b70608..43610b3 100644 --- a/doc/Jamfile +++ b/doc/Jamfile @@ -29,7 +29,7 @@ else if [ os.name ] = LINUX : $(BOOST_ROOT)3rdParty/boost-doc/saxon/Saxon-HE.jar : /usr/bin/java ; - using quickbook : $(BOOST_ROOT)build/linux-debian7-x64-release/bin/quickbook ; + using quickbook : $(BOOST_ROOT)build/linux-native-x64-release/bin/quickbook ; } import boostbook ; @@ -67,7 +67,7 @@ docca.reference reference.qbk OUTPUT_LANGUAGE=English INLINE_INHERITED_MEMB=YES AUTOLINK_SUPPORT=NO - BRIEF_MEMBER_DESC=NO + BRIEF_MEMBER_DESC=NO EXTRACT_ALL=YES HAVE_DOT=NO HIDE_UNDOC_MEMBERS=YES diff --git a/doc/qbk/00_main.qbk b/doc/qbk/00_main.qbk index 65a3384..5f7690d 100644 --- a/doc/qbk/00_main.qbk +++ b/doc/qbk/00_main.qbk @@ -26,7 +26,9 @@ [template asioreflink[id term][@boost:/doc/html/boost_asio/reference/[id].html [^boost::asio::[term]]]] [template beastreflink[id term][@boost:/libs/beast/doc/html/beast/ref/[id].html [^boost::beast::[term]]]] [template beastconceptslink[id term][@boost:/libs/beast/doc/html/beast/concepts/[id].html [term]]] +[template mqttlink[id text][@https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc[id] [text]]] +[def __CompletionToken__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.completion_tokens_and_handlers ['CompletionToken]]] [def __ExecutionContext__ [reflink2 ExecutionContext ['ExecutionContext]]] [def __StreamType__ [reflink2 StreamType ['StreamType]]] [def __TlsContext__ [reflink2 TlsContext ['TlsContext]]] @@ -37,17 +39,36 @@ [/ MQTT stuff] [def __MQTT__ [@https://mqtt.org/ MQTT]] +[def __UTF8_STRING_PAIR__ [mqttlink 3901013 `UTF-8 String Pair`]] +[def __PACKET_SIZE__ [mqttlink 3901024 `packet size`]] +[def CONNECT [mqttlink 3901033 `CONNECT`]] +[def CONNACK [mqttlink 3901074 `CONNACK`]] +[def PUBLISH [mqttlink 3901100 `PUBLISH`]] +[def PUBACK [mqttlink 3901121 `PUBACK`]] +[def PUBREC [mqttlink 3901131 `PUBREC`]] +[def PUBREL [mqttlink 3901141 `PUBREL`]] +[def PUBCOMP [mqttlink 3901151 `PUBCOMP`]] +[def SUBSCRIBE [mqttlink 3901161 `SUBSCRIBE`]] +[def SUBACK [mqttlink 3901171 `SUBACK`]] +[def UNSUBSCRIBE [mqttlink 3901179 `UNSUBSCRIBE`]] +[def UNSUBACK [mqttlink 3901187 `UNSUBACK`]] +[def PINGREQ [mqttlink 3901195 `PINGREQ`]] +[def PINGRESP [mqttlink 3901200 `PINGRESP`]] +[def DISCONNECT [mqttlink 3901205 `DISCONNECT`]] +[def AUTH [mqttlink 3901217 `AUTH`]] [include 01_intro.qbk] [section:ref Reference] -[xinclude helpers/quickref.xml] +[xinclude reference/quickref.xml] + [block''''''] [include reference.qbk] -[include helpers/ExecutionContext.qbk] -[include helpers/StreamType.qbk] -[include helpers/TlsContext.qbk] -[include helpers/Reason_codes.qbk] +[include reference/ExecutionContext.qbk] +[include reference/StreamType.qbk] +[include reference/TlsContext.qbk] +[include reference/reason_codes/Reason_codes.qbk] +[include reference/properties/Properties.qbk] [block''''''] [endsect] diff --git a/doc/qbk/helpers/Reason_codes.qbk b/doc/qbk/helpers/Reason_codes.qbk deleted file mode 100644 index 9d08074..0000000 --- a/doc/qbk/helpers/Reason_codes.qbk +++ /dev/null @@ -1,114 +0,0 @@ -[/ - Copyright (c) 2023 Mireo - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -] - - -[section:async_mqtt5__Reason_codes Reason codes] - -This section lists all possible reason codes that Broker can send in a -MQTT Control Packet. - -Reason codes indicating successful completion of an operation: - -[reflink2 reason_codes__success success] - -[reflink2 reason_codes__normal_disconnection normal_disconnection] - -[reflink2 reason_codes__granted_qos_0 granted_qos_0] - -[reflink2 reason_codes__granted_qos_1 granted_qos_1] - -[reflink2 reason_codes__granted_qos_2 granted_qos_2] - -[reflink2 reason_codes__disconnect_with_will_message disconnect_with_will_message] - -[reflink2 reason_codes__no_matching_subscribers no_matching_subscribers] - -[reflink2 reason_codes__no_subscription_existed no_subscription_existed] - -[reflink2 reason_codes__continue_authentication continue_authentication] - -[reflink2 reason_codes__reauthenticate reauthenticate] - - -Reason codes indicating an error during packet exchange: - -[reflink2 reason_codes__unspecified_error unspecified_error] - -[reflink2 reason_codes__malformed_packet malformed_packet] - -[reflink2 reason_codes__protocol_error protocol_error] - -[reflink2 reason_codes__implementation_specific_error implementation_specific_error] - -[reflink2 reason_codes__unsupported_protocol_version unsupported_protocol_version] - -[reflink2 reason_codes__client_id_not_valid client_id_not_valid] - -[reflink2 reason_codes__bad_username_or_password bad_username_or_password] - -[reflink2 reason_codes__not_authorized not_authorized] - -[reflink2 reason_codes__server_unavailable server_unavailable] - -[reflink2 reason_codes__server_busy server_busy] - -[reflink2 reason_codes__banned banned] - -[reflink2 reason_codes__server_shutting_down server_shutting_down] - -[reflink2 reason_codes__bad_authentication_method bad_authentication_method] - -[reflink2 reason_codes__keep_alive_timeout keep_alive_timeout] - -[reflink2 reason_codes__session_taken_over session_taken_over] - -[reflink2 reason_codes__topic_filter_invalid topic_filter_invalid] - -[reflink2 reason_codes__topic_name_invalid topic_name_invalid] - -[reflink2 reason_codes__packet_id_in_use packet_id_in_use] - -[reflink2 reason_codes__packet_id_not_found packet_id_not_found] - -[reflink2 reason_codes__receive_maximum_exceeded receive_maximum_exceeded] - -[reflink2 reason_codes__topic_alias_invalid topic_alias_invalid] - -[reflink2 reason_codes__packet_too_large packet_too_large] - -[reflink2 reason_codes__message_rate_too_high message_rate_too_high] - -[reflink2 reason_codes__quota_exceeded quota_exceeded] - -[reflink2 reason_codes__administrative_action administrative_action] - -[reflink2 reason_codes__payload_format_invalid payload_format_invalid] - -[reflink2 reason_codes__retain_not_supported retain_not_supported] - -[reflink2 reason_codes__qos_not_supported qos_not_supported] - -[reflink2 reason_codes__use_another_server use_another_server] - -[reflink2 reason_codes__server_moved server_moved] - -[reflink2 reason_codes__shared_subscriptions_not_supported shared_subscriptions_not_supported] - -[reflink2 reason_codes__connection_rate_exceeded connection_rate_exceeded] - -[reflink2 reason_codes__maximum_connect_time maximum_connect_time] - -[reflink2 reason_codes__subscription_ids_not_supported subscription_ids_not_supported] - -[reflink2 reason_codes__wildcard_subscriptions_not_supported wildcard_subscriptions_not_supported] - - -Special reason code: - -[reflink2 reason_codes__empty empty] - -[endsect] \ No newline at end of file diff --git a/doc/qbk/helpers/ExecutionContext.qbk b/doc/qbk/reference/ExecutionContext.qbk similarity index 98% rename from doc/qbk/helpers/ExecutionContext.qbk rename to doc/qbk/reference/ExecutionContext.qbk index e3cf4b4..ca01e9c 100644 --- a/doc/qbk/helpers/ExecutionContext.qbk +++ b/doc/qbk/reference/ExecutionContext.qbk @@ -13,4 +13,4 @@ is a base class for concrete execution context types. The [asioreflink io_context io_context] type is an example of a derived type. -[endsect] \ No newline at end of file +[endsect] diff --git a/doc/qbk/helpers/StreamType.qbk b/doc/qbk/reference/StreamType.qbk similarity index 90% rename from doc/qbk/helpers/StreamType.qbk rename to doc/qbk/reference/StreamType.qbk index efd20de..20ef253 100644 --- a/doc/qbk/helpers/StreamType.qbk +++ b/doc/qbk/reference/StreamType.qbk @@ -9,7 +9,7 @@ `StreamType` represents the transport protocol type used to transfer stream of bytes. -`StreamType` should meet the [beastconceptslink streams Stream] concept. +`StreamType` should meet the [beastconceptslink streams AsyncStream] concept. Additionally, it should follow Asio's layered stream model by having a `lowest_layer_type` member type, and a `lowest_layer` member function, returing a `lowest_layer_type&`. @@ -20,4 +20,4 @@ The types [asioreflink basic_stream_socket basic_stream_socket] meet these requirements. -[endsect] \ No newline at end of file +[endsect] diff --git a/doc/qbk/helpers/TlsContext.qbk b/doc/qbk/reference/TlsContext.qbk similarity index 97% rename from doc/qbk/helpers/TlsContext.qbk rename to doc/qbk/reference/TlsContext.qbk index 5491f21..018db3b 100644 --- a/doc/qbk/helpers/TlsContext.qbk +++ b/doc/qbk/reference/TlsContext.qbk @@ -11,4 +11,4 @@ The type [asioreflink ssl__context ssl::context] meets these requirements. -[endsect] \ No newline at end of file +[endsect] diff --git a/doc/qbk/reference/properties/Properties.qbk b/doc/qbk/reference/properties/Properties.qbk new file mode 100644 index 0000000..748fd11 --- /dev/null +++ b/doc/qbk/reference/properties/Properties.qbk @@ -0,0 +1,151 @@ +[/ + Copyright (c) 2023 Mireo + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +] + + +[section:async_mqtt5__Properties Properties] + +The last field in the Variable header of packets CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC,PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, and AUTH +is a set of Properties. A set contains a Property Length followed by the Properties. A Property consists of an Identifier and a value. + +This section lists all possible Properties and describes their usage: + +[table:connect_props CONNECT properties + [[Identifier] [Value type] [Description]] + [[session_expiry_interval] [`int32_t`] [Represents the Session Expiry Internal in seconds.]] + [[receive_maximum] [`int16_t`] [The maximum number of QoS 1 and QoS 2 publications that the Client is willing to process concurrently.]] + [[maximum_packet_size] [`int32_t`] [The maximum __PACKET_SIZE__ in bytes that the Client is willing to process.]] + [[topic_alias_maximum] [`uint16_t`] [The highest value that the Client will accept as a Topic Alias sent by the Server.]] + [[request_response_information] [`uint8_t`] [The value of 0 signals that the Server MUST NOT return Response Information in CONNACK. If the value if 1, it MAY return it.]] + [[request_problem_information] [`uint8_t`] [The value of 0 signals that the Server MAY return a Reason String or User Properties on a CONNACK or DISCONNECT packet, + but MUST NOT send them on any packet other than PUBLISH, CONNACK, or DISCONNECT. If the value is 1, the Server MAY return a Reason String or User Properties where it is allowed.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + The meaning of these properties is not defined by the specification.]] + [[authentication_method] [`std::string`] [A UTF-8 Encoded String containing the name of the authentication method used for extended authentication.]] + [[authentication_data] [`std::string`] [Binary Data containing authentication data. The contents of the data are defined by the authentication method.]] +] + +[table:will_props Will properties + [[Identifier] [Value type] [Description]] + [[will_delay_interval] [`int32_t`] [The delay in seconds that need to pass before Server publishes the Client's Will Message.]] + [[payload_format_indicator] [`uint8_t`] [Value of 0 indicates that the Will Message is in unspecified bytes. Value of 1 indicates that the Will Message is UTF-8 Encoded Character Data.]] + [[message_expiry_interval] [`int32_t`] [The lifetime of the Will Message in seconds. It is send as Publication Expiry Interval when it is published.]] + [[content_type] [`std::string`] [A UTF-8 Encoded String describing the content of the Will Message.]] + [[response_topic] [`std::string`] [A UTF-8 Encoded String which is used as the Topic Name for a response message.]] + [[correlation_data] [`std::string`] [Binary Data used by the sender of the Request Message to identify which request the Response Message is for when it is received.]] + [[correlation_data] [`std::string`] [Binary Data used by the sender of the Request Message to identify which request the Response Message is for when it is received.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + The meaning of these properties is not defined by the specification.]] +] + +[table:connack_props CONNACK properties + [[Identifier] [Value type] [Description]] + [[session_expiry_interval] [`int32_t`] [Represents the Session Expiry Internal in seconds.]] + [[receive_maximum] [`int16_t`] [The maximum number of QoS 1 and QoS 2 publications that the Server is willing to process concurrently.]] + [[maximum_qos] [`uint8_t`] [The highest QoS the Server supports.]] + [[retain_available] [`uint8_t`] [A value of 0 means that retained message are not supported. A value of 1 means they are supported.]] + [[maximum_packet_size] [`int32_t`] [The maximum __PACKET_SIZE__ in bytes that the Server is willing to accept.]] + [[assigned_client_identifier] [`std::string`] [The Client Identifier which was assigned by the Server because a zero length Client Identifier was found in the CONNECT packet]] + [[topic_alias_maximum] [`uint16_t`] [The highest value that the Server will accept as a Topic Alias sent by the Client.]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[correlation_data] [`std::string`] [Binary Data used by the sender of the Request Message to identify which request the Response Message is for when it is received.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + The meaning of these properties is not defined by the specification.]] + [[server_keep_alive] [`int16_t`] [The Keep Alive time assigned by the Server.]] + [[response_information] [`std::string`] [A UTF-8 Encoded String which is used as the basis for creating a Response Topic.]] + [[server_reference] [`std::string`] [A UTF-8 Encoded String which can be used by the Client to identfy another Server to use.]] + [[authentication_method] [`std::string`] [A UTF-8 Encoded String containing the name of the authentication method used for extended authentication.]] + [[authentication_data] [`std::string`] [Binary Data containing authentication data. The contents of the data are defined by the authentication method.]] +] + +[table:publish_props PUBLISH properties + [[Identifier] [Value type] [Description]] + [[payload_format_indicator] [`uint8_t`] [Value of 0 indicates that the Payload is in unspecified bytes. Value of 1 indicates that the Payload is UTF-8 Encoded Character Data.]] + [[message_expiry_interval] [`int32_t`] [The lifetime of the Application Message in seconds.]] + [[topic_alias] [`int16_t`] [Two Byte integer representing the Topic Alias, an integer value that is used to identify the Topic instead of using the Topic Name.]] + [[response_topic] [`std::string`] [A UTF-8 Encoded String which is used as the Topic Name for a response message.]] + [[correlation_data] [`std::string`] [Binary Data used by the sender of the Request Message to identify which request the Response Message is for when it is received.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + The meaning of these properties is not defined by the specification.]] + [[subscription_identifier] [`uint32_t`] [Identifier of the Subscription in range of 1 to 268,435,455.]] + [[content_type] [`std::string`] [A UTF-8 Encoded String describing the content of the Application Message.]] +] + +[table:puback_props PUBACK properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:pubrec_props PUBREC properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:pubrel_props PUBREL properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:pubcomp_props PUBCOMP properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:subscribe_props SUBSCRIBE properties + [[Identifier] [Value type] [Description]] + [[subscription_identifier] [`uint32_t`] [Identifier of the Subscription in range of 1 to 268,435,455.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property can be used to send subscription related properties from the Client to the Server. + The meaning of these properties is not defined by the specification ]] +] + +[table:suback_props SUBACK properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:unsubscribe_props UNSUBSCRIBE properties + [[Identifier] [Value type] [Description]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property can be used to send subscription related properties from the Client to the Server. + The meaning of these properties is not defined by the specification ]] +] + +[table:unsuback_props UNSUBACK properties + [[Identifier] [Value type] [Description]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:disconnect_props DISCONNECT properties + [[Identifier] [Value type] [Description]] + [[session_expiry_interval] [`int32_t`] [Represents the Session Expiry Internal in seconds. Can only be sent by the Client.]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[table:auth_props AUTH properties + [[Identifier] [Value type] [Description]] + [[authentication_method] [`std::string`] [A UTF-8 Encoded String containing the name of the authentication method used for extended authentication.]] + [[authentication_data] [`std::string`] [Binary Data containing authentication data. The contents of the data are defined by the authentication method.]] + [[reason_string] [`std::string`] [A UTF-8 Encoded String representing the reason associated with this response.]] + [[user_property] [`std::vector`] [A list of name, value pairs (__UTF8_STRING_PAIR__) defining User Properties. + This property may be used to provide additional diagnostic or other information. ]] +] + +[endsect] \ No newline at end of file diff --git a/doc/qbk/helpers/quickref.xml b/doc/qbk/reference/quickref.xml similarity index 93% rename from doc/qbk/helpers/quickref.xml rename to doc/qbk/reference/quickref.xml index 979e2e7..a1c1882 100644 --- a/doc/qbk/helpers/quickref.xml +++ b/doc/qbk/reference/quickref.xml @@ -49,6 +49,10 @@ + Properties + + Properties + Functions get_error_code_category diff --git a/doc/qbk/reference/reason_codes/Reason_codes.qbk b/doc/qbk/reference/reason_codes/Reason_codes.qbk new file mode 100644 index 0000000..11d908d --- /dev/null +++ b/doc/qbk/reference/reason_codes/Reason_codes.qbk @@ -0,0 +1,16 @@ +[/ + Copyright (c) 2023 Mireo + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +] + + +[section:async_mqtt5__Reason_codes Reason codes] + +This section lists all possible reason codes that can be sent in a +MQTT Control Packet. + +[xinclude rcref.xml] + +[endsect] diff --git a/doc/qbk/helpers/rcref.xml b/doc/qbk/reference/reason_codes/rcref.xml similarity index 95% rename from doc/qbk/helpers/rcref.xml rename to doc/qbk/reference/reason_codes/rcref.xml index 7ea5058..ae59fc1 100644 --- a/doc/qbk/helpers/rcref.xml +++ b/doc/qbk/reference/reason_codes/rcref.xml @@ -15,56 +15,56 @@ Success - success - normal_disconnection + continue_authentication + disconnect_with_will_message granted_qos_0 granted_qos_1 granted_qos_2 - disconnect_with_will_message no_matching_subscribers no_subscription_existed - continue_authentication + normal_disconnection + reauthenticate + success Error - unspecified_error - malformed_packet - protocol_error - implementation_specific_error - unsupported_protocol_version - client_id_not_valid - bad_username_or_password - not_authorized - server_unavailable - server_busy - banned - server_shutting_down + administrative_action bad_authentication_method + bad_username_or_password + banned + client_id_not_valid + connection_rate_exceeded + implementation_specific_error keep_alive_timeout - session_taken_over - topic_filter_invalid - topic_name_invalid + maximum_connect_time + message_rate_too_high + not_authorized packet_id_in_use packet_id_not_found - receive_maximum_exceeded - topic_alias_invalid packet_too_large - message_rate_too_high - quota_exceeded - administrative_action payload_format_invalid - retain_not_supported qos_not_supported - use_another_server + quota_exceeded + receive_maximum_exceeded + retain_not_supported + server_busy server_moved + server_shutting_down + server_unavailable + session_taken_over shared_subscriptions_not_supported - connection_rate_exceeded - maximum_connect_time subscription_ids_not_supported + topic_alias_invalid + topic_filter_invalid + topic_name_invalid + unsupported_protocol_version + use_another_server wildcard_subscriptions_not_supported + + Special empty diff --git a/example/tcp.cpp b/example/tcp.cpp index 610ab3c..0c987c2 100644 --- a/example/tcp.cpp +++ b/example/tcp.cpp @@ -24,7 +24,7 @@ void publish_qos0_tcp() { c.async_publish( "test/mqtt-test", "hello world with qos0!", - retain_e::no, publish_props {}, + retain_e::no, publish_props{}, [&c](error_code ec) { fmt::print("\terror_code: {}\n", ec.message()); c.cancel(); diff --git a/include/async_mqtt5/error.hpp b/include/async_mqtt5/error.hpp index 4e23218..9fe43c2 100644 --- a/include/async_mqtt5/error.hpp +++ b/include/async_mqtt5/error.hpp @@ -14,11 +14,11 @@ namespace async_mqtt5 { * in the DISCONNECT packet as the reason for the disconnection. */ enum class disconnect_rc_e : std::uint8_t { - /// Close the connection normally. Do not send the \ref will Message. + /** Close the connection normally. Do not send the \ref will Message. */ normal_disconnection = 0x00, - /// The Client wishes to disconnect but requires that - /// the Server also publishes its \ref will Message. + /** The Client wishes to disconnect but requires that + the Server also publishes its \ref will Message. */ disconnect_with_will_message = 0x04, // TODO: these reason codes should not be available to the user, only the client @@ -43,29 +43,29 @@ namespace client { * \details Represents error that occur on the client side. */ enum class error : int { - /// [unused] A fatal error occurred. + /** [unused] A fatal error occurred. */ fatal_error = 100, - /// Malformed packet has been detected. + /** Malformed packet has been detected. */ malformed_packet, - /// There are no more available Packet Identifiers to use. + /** There are no more available Packet Identifiers to use. */ pid_overrun, - /// [unused] The Client has reconnected. + /** [unused] The Client has reconnected. */ reconnected, - /// The Client has been disconnected. + /** The Client has been disconnected. */ disconnected, // publish - /// The Server does not support the specified \ref qos_e. + /** The Server does not support the specified \ref qos_e. */ qos_not_supported, - /// The Server dos not support retained messages. + /** The Server dos not support retained messages. */ retain_not_available, - /// The Client attempted to send a Topic Alias that is greater than Topic Alias Maximum. + /** The Client attempted to send a Topic Alias that is greater than Topic Alias Maximum. */ topic_alias_maximum_reached }; @@ -199,14 +199,15 @@ public: if (_category == suback) return "The subscription is accepted with maximum QoS sent at 0"; if (_category == disconnect) - return "Close the connection normally"; + return "Close the connection normally. Do not send the Will Message"; return "The operation completed successfully"; case 0x01: return "The subscription is accepted with maximum QoS sent at 1"; case 0x02: return "The subscription is accepted with maximum QoS sent at 2"; case 0x04: - return "The Client wishes to disconnect with the Will Message"; + return "The Client wishes to disconnect but requires" + "that the Server also publishes its Will Message"; case 0x10: return "The message is accepted but there are no subscribers"; case 0x11: @@ -216,7 +217,8 @@ public: case 0x19: return "Initiate a re-authentication"; case 0x80: - return "Unspecified error occurred"; + return "The Server does not wish to reveal the reason for the" + "failure, or none of the other Reason Codes apply"; case 0x81: return "Data within the packet could not be correctly parsed"; case 0x82: @@ -249,7 +251,7 @@ public: return "Another Connection using the same ClientID has connected " "causing this Connection to be closed"; case 0x8f: - return "The Topic Name is not malformed, but it is not accepted"; + return "The Topic Filer is not malformed, but it is not accepted"; case 0x90: return "The Topic Name is not malformed, but it is not accepted"; case 0x91: @@ -295,7 +297,7 @@ public: case 0xff: return "No reason code"; default: - return "Invalid reason code."; + return "Invalid reason code"; } } }; @@ -303,54 +305,153 @@ public: namespace reason_codes { using enum category; + +/** No Reason Code. A \ref client::error occurred.*/ constexpr reason_code empty {}; -constexpr reason_code success { 0x00 }; -constexpr reason_code normal_disconnection { 0x00, disconnect }; -constexpr reason_code granted_qos_0 { 0x00, suback }; -constexpr reason_code granted_qos_1 { 0x01 }; -constexpr reason_code granted_qos_2 { 0x02 }; -constexpr reason_code disconnect_with_will_message { 0x04 }; -constexpr reason_code no_matching_subscribers { 0x10 }; -constexpr reason_code no_subscription_existed { 0x11 }; -constexpr reason_code continue_authentication { 0x18 }; -constexpr reason_code reauthenticate { 0x19 }; +/** The operation completed successfully. */ +constexpr reason_code success{ 0x00 }; -constexpr reason_code unspecified_error { 0x80 }; -constexpr reason_code malformed_packet { 0x81 }; -constexpr reason_code protocol_error { 0x82 }; -constexpr reason_code implementation_specific_error { 0x83 }; -constexpr reason_code unsupported_protocol_version { 0x84 }; -constexpr reason_code client_id_not_valid { 0x85 }; -constexpr reason_code bad_username_or_password { 0x86 }; -constexpr reason_code not_authorized { 0x87 }; -constexpr reason_code server_unavailable { 0x88 }; -constexpr reason_code server_busy { 0x89 }; -constexpr reason_code banned { 0x8a }; -constexpr reason_code server_shutting_down { 0x8b }; -constexpr reason_code bad_authentication_method { 0x8c }; -constexpr reason_code keep_alive_timeout { 0x8d }; -constexpr reason_code session_taken_over { 0x8e }; -constexpr reason_code topic_filter_invalid { 0x8f }; -constexpr reason_code topic_name_invalid { 0x90 }; -constexpr reason_code packet_id_in_use { 0x91 }; -constexpr reason_code packet_id_not_found { 0x92 }; -constexpr reason_code receive_maximum_exceeded { 0x93 }; -constexpr reason_code topic_alias_invalid { 0x94 }; -constexpr reason_code packet_too_large { 0x95 }; -constexpr reason_code message_rate_too_high { 0x96 }; -constexpr reason_code quota_exceeded { 0x97 }; -constexpr reason_code administrative_action { 0x98 }; -constexpr reason_code payload_format_invalid { 0x99 }; -constexpr reason_code retain_not_supported { 0x9a }; -constexpr reason_code qos_not_supported { 0x9b }; -constexpr reason_code use_another_server { 0x9c }; -constexpr reason_code server_moved { 0x9d }; -constexpr reason_code shared_subscriptions_not_supported { 0x9e }; -constexpr reason_code connection_rate_exceeded { 0x9f }; -constexpr reason_code maximum_connect_time { 0xa0 }; -constexpr reason_code subscription_ids_not_supported { 0xa1 }; -constexpr reason_code wildcard_subscriptions_not_supported { 0xa2 }; +/** Close the connection normally. Do not send the Will Message. */ +constexpr reason_code normal_disconnection{ 0x00, disconnect }; + +/** The subscription is accepted with maximum QoS sent at 0. */ +constexpr reason_code granted_qos_0{ 0x00, suback }; + +/** The subscription is accepted with maximum QoS sent at 1. */ +constexpr reason_code granted_qos_1{ 0x01 }; + +/** The subscription is accepted with maximum QoS sent at 2 */ +constexpr reason_code granted_qos_2{ 0x02 }; + +/** The Client wishes to disconnect but requires that + the Server also publishes its Will Message. */ +constexpr reason_code disconnect_with_will_message{ 0x04 }; + +/** The message is accepted but there are no subscribers. */ +constexpr reason_code no_matching_subscribers{ 0x10 }; + +/** No matching Topic Filter is being used by the Client. */ +constexpr reason_code no_subscription_existed{ 0x11 }; + +/** Continue the authentication with another step. */ +constexpr reason_code continue_authentication{ 0x18 }; + +/** Initiate a re-authentication. */ +constexpr reason_code reauthenticate{ 0x19 }; + +/** The Server does not wish to reveal the reason for the + failure, or none of the other Reason Codes apply. */ +constexpr reason_code unspecified_error{ 0x80 }; + +/** Data within the packet could not be correctly parsed. */ +constexpr reason_code malformed_packet{ 0x81 }; + +/** Data in the packet does not conform to this specification. */ +constexpr reason_code protocol_error{ 0x82 }; + +/** The packet is valid but not accepted by this Server. */ +constexpr reason_code implementation_specific_error{ 0x83 }; + +/** The Server does not support the requested version of the MQTT protocol. */ +constexpr reason_code unsupported_protocol_version{ 0x84 }; + +/** The Client ID is valid but not allowed by this Server. */ +constexpr reason_code client_id_not_valid{ 0x85 }; + +/** The Server does not accept the User Name or Password provided. */ +constexpr reason_code bad_username_or_password{ 0x86 }; + +/** The request is not authorized. */ +constexpr reason_code not_authorized{ 0x87 }; + +/** The MQTT Server is not available. */ +constexpr reason_code server_unavailable{ 0x88 }; + +/** The MQTT Server is busy, try again later. */ +constexpr reason_code server_busy{ 0x89 }; + +/** The Client has been banned by administrative action. */ +constexpr reason_code banned{ 0x8a }; + +/** The Server is shutting down. */ +constexpr reason_code server_shutting_down{ 0x8b }; + +/** The authentication method is not supported or + does not match the method currently in use. */ +constexpr reason_code bad_authentication_method{ 0x8c }; + +/** No packet has been received for 1.5 times the Keepalive time. */ +constexpr reason_code keep_alive_timeout{ 0x8d }; + +/** Another Connection using the same ClientID has connected + causing this Connection to be closed. */ +constexpr reason_code session_taken_over{ 0x8e }; + +/** The Topic Filter is not malformed, but it is not accepted. */ +constexpr reason_code topic_filter_invalid{ 0x8f }; + + +/** The Topic Name is not malformed, but it is not accepted. */ +constexpr reason_code topic_name_invalid{ 0x90 }; + +/** The Packet Identifier is already in use. */ +constexpr reason_code packet_id_in_use{ 0x91 }; + +/** The Packet Identifier is not known. */ +constexpr reason_code packet_id_not_found{ 0x92 }; + +/** The Client or Server has received more than Receive + Maximum publication for which it has not sent PUBACK or PUBCOMP. */ +constexpr reason_code receive_maximum_exceeded{ 0x93 }; + +/** The Client or Server received a PUBLISH packet containing + a Topic Alias greater than the Maximum Topic Alias. */ +constexpr reason_code topic_alias_invalid{ 0x94 }; + +/** The packet exceeded the maximum permissible size. */ +constexpr reason_code packet_too_large{ 0x95 }; + +/** The received data rate is too high. */ +constexpr reason_code message_rate_too_high{ 0x96 }; + +/** An implementation or administrative imposed limit has been exceeded. */ +constexpr reason_code quota_exceeded{ 0x97 }; + +/** The Connection is closed due to an administrative action. */ +constexpr reason_code administrative_action{ 0x98 }; + +/** The Payload does not match the specified Payload Format Indicator. */ +constexpr reason_code payload_format_invalid{ 0x99 }; + +/** The Server does not support retained messages. */ +constexpr reason_code retain_not_supported{ 0x9a }; + +/** The Server does not support the QoS the Client specified or + it is greater than the Maximum QoS specified. */ +constexpr reason_code qos_not_supported{ 0x9b }; + +/** The Client should temporarily use another server. */ +constexpr reason_code use_another_server{ 0x9c }; + +/** The Client should permanently use another server. */ +constexpr reason_code server_moved{ 0x9d }; + +/** The Server does not support Shared Subscriptions for this Client. */ +constexpr reason_code shared_subscriptions_not_supported{ 0x9e }; + +/** The connection rate limit has been exceeded. */ +constexpr reason_code connection_rate_exceeded{ 0x9f }; + +/** The maximum connection time authorized for this + connection has been exceeded. */ +constexpr reason_code maximum_connect_time{ 0xa0 }; + +/** The Server does not support Subscription Identifiers. */ +constexpr reason_code subscription_ids_not_supported{ 0xa1 }; + +/** The Server does not support Wildcard Subscriptions. */ +constexpr reason_code wildcard_subscriptions_not_supported{ 0xa2 }; namespace detail { diff --git a/include/async_mqtt5/mqtt_client.hpp b/include/async_mqtt5/mqtt_client.hpp index 2434c6b..ab66d91 100644 --- a/include/async_mqtt5/mqtt_client.hpp +++ b/include/async_mqtt5/mqtt_client.hpp @@ -126,7 +126,8 @@ public: /** * \brief Cancel all asynchronous operations. * - * \details All outstanding operations will complete with `boost::asio::error::operation_aborted`. + * \details All outstanding operations will complete + * with `boost::asio::error::operation_aborted`. */ void cancel() { get_executor().execute([svc_ptr = _svc_ptr]() { @@ -137,7 +138,9 @@ public: /** * \brief Assign a \ref will Message. * - * \details The \ref will Message that will be published after the Network Connection is closed. + * \details The \ref will Message that the Broker should publish + * after the Network Connection is closed and it is not + * closed normally. */ mqtt_client& will(will will) { _svc_ptr->will(std::move(will)); @@ -324,7 +327,7 @@ public: * to Topics that the Client subscribed to. The PUBLISH packets can be received * with \ref mqtt_client::async_receive function. * - * \param topic \ref subscribe_topic of interest. + * \param topic A \ref subscribe_topic of interest. * \param props SUBSCRIBE properties. * \param token Completion token that will be used to produce a * completion handler, which will be called when the operation completed. @@ -519,7 +522,8 @@ public: * \par Error codes * The list of all possible error codes that this operation can finish with:\n * - `boost::system::errc::errc_t::success`\n - * - `boost::asio::error::try_again` -- why? + * - `boost::asio::operation_aborted`\n + * - `boost::asio::no_recovery`\n */ template decltype(auto) async_disconnect( @@ -555,7 +559,8 @@ public: * \par Error codes * The list of all possible error codes that this operation can finish with:\n * - `boost::system::errc::errc_t::success`\n - * - `boost::asio::error::try_again` -- why? + * - `boost::asio::operation_aborted`\n + * - `boost::asio::no_recovery`\n */ template decltype(auto) async_disconnect(CompletionToken&& token) { diff --git a/include/async_mqtt5/property_types.hpp b/include/async_mqtt5/property_types.hpp index e1c3eae..819a6b6 100644 --- a/include/async_mqtt5/property_types.hpp +++ b/include/async_mqtt5/property_types.hpp @@ -9,33 +9,33 @@ namespace async_mqtt5::prop { -constexpr std::integral_constant payload_format_indicator{}; -constexpr std::integral_constant message_expiry_interval{}; -constexpr std::integral_constant content_type{}; -constexpr std::integral_constant response_topic{}; -constexpr std::integral_constant correlation_data{}; -constexpr std::integral_constant subscription_identifier{}; -constexpr std::integral_constant session_expiry_interval{}; -constexpr std::integral_constant assigned_client_identifier{}; -constexpr std::integral_constant server_keep_alive{}; -constexpr std::integral_constant authentication_method{}; -constexpr std::integral_constant authentication_data{}; -constexpr std::integral_constant request_problem_information{}; -constexpr std::integral_constant will_delay_interval{}; -constexpr std::integral_constant request_response_information{}; -constexpr std::integral_constant response_information{}; -constexpr std::integral_constant server_reference{}; -constexpr std::integral_constant reason_string{}; -constexpr std::integral_constant receive_maximum{}; -constexpr std::integral_constant topic_alias_maximum{}; -constexpr std::integral_constant topic_alias{}; -constexpr std::integral_constant maximum_qos{}; -constexpr std::integral_constant retain_available{}; -constexpr std::integral_constant user_property{}; -constexpr std::integral_constant maximum_packet_size{}; -constexpr std::integral_constant wildcard_subscription_available{}; -constexpr std::integral_constant subscription_identifier_available{}; -constexpr std::integral_constant shared_subscription_available{}; +constexpr std::integral_constant payload_format_indicator {}; +constexpr std::integral_constant message_expiry_interval {}; +constexpr std::integral_constant content_type {}; +constexpr std::integral_constant response_topic {}; +constexpr std::integral_constant correlation_data {}; +constexpr std::integral_constant subscription_identifier {}; +constexpr std::integral_constant session_expiry_interval {}; +constexpr std::integral_constant assigned_client_identifier {}; +constexpr std::integral_constant server_keep_alive {}; +constexpr std::integral_constant authentication_method {}; +constexpr std::integral_constant authentication_data {}; +constexpr std::integral_constant request_problem_information {}; +constexpr std::integral_constant will_delay_interval {}; +constexpr std::integral_constant request_response_information {}; +constexpr std::integral_constant response_information {}; +constexpr std::integral_constant server_reference {}; +constexpr std::integral_constant reason_string {}; +constexpr std::integral_constant receive_maximum {}; +constexpr std::integral_constant topic_alias_maximum {}; +constexpr std::integral_constant topic_alias {}; +constexpr std::integral_constant maximum_qos {}; +constexpr std::integral_constant retain_available {}; +constexpr std::integral_constant user_property {}; +constexpr std::integral_constant maximum_packet_size {}; +constexpr std::integral_constant wildcard_subscription_available {}; +constexpr std::integral_constant subscription_identifier_available {}; +constexpr std::integral_constant shared_subscription_available {}; template struct property_traits; diff --git a/include/async_mqtt5/types.hpp b/include/async_mqtt5/types.hpp index bab4019..9c322a2 100644 --- a/include/async_mqtt5/types.hpp +++ b/include/async_mqtt5/types.hpp @@ -6,12 +6,11 @@ #include -#include #include namespace async_mqtt5 { -/// An alias for `boost::system::error_code`; +/** An alias for `boost::system::error_code`; */ using error_code = boost::system::error_code; struct authority_path { @@ -25,14 +24,14 @@ struct authority_path { * to the receiver. */ enum class qos_e : std::uint8_t { - /// The message arrives at the receiver either once or not at all. + /** The message arrives at the receiver either once or not at all. */ at_most_once = 0b00, - /// Ensures the message arrives at the receiver at least once. + /** Ensures the message arrives at the receiver at least once. */ at_least_once = 0b01, - /// All messages arrive at the receiver exactly once without - /// loss or duplication of the messages. + /** All messages arrive at the receiver exactly once without + loss or duplication of the messages. */ exactly_once = 0b10 }; @@ -43,16 +42,16 @@ enum class qos_e : std::uint8_t { * store the current message. */ enum class retain_e : std::uint8_t { - /// The Server will replace any existing retained message for this Topic - /// with this message. + /** The Server will replace any existing retained message for this Topic + with this message. */ yes = 0b1, - /// The Server will not store this message and will not remove or replace - /// any existing retained message. + /** The Server will not store this message and will not remove or replace + any existing retained message. */ no = 0b0 }; -// TODO: should this be moved to internal types? + enum class dup_e : std::uint8_t { yes = 0b1, no = 0b0 }; @@ -62,7 +61,9 @@ enum class dup_e : std::uint8_t { * \brief Represents the Options associated with each Subscription. */ struct subscribe_options { + /** + * * \brief Representation of the No Local Subscribe Option. * * \details A Subscribe Option indicating whether or not Application Messages @@ -70,10 +71,10 @@ struct subscribe_options { * publishing connection. */ enum class no_local_e : std::uint8_t { - /// Application Messages can be forwarded to a connection with equal ClientID. + /** Application Messages can be forwarded to a connection with equal ClientID. */ no = 0b0, - /// Application Messages MUST NOT be forwarded to a connection with equal ClientID. + /** Application Messages MUST NOT be forwarded to a connection with equal ClientID. */ yes = 0b1 }; @@ -84,10 +85,10 @@ struct subscribe_options { * using this subscription keep the \ref retain_e flag they were published with. */ enum class retain_as_published_e : std::uint8_t { - /// Application Messages have the \ref retain_e flag set to 0. + /** Application Messages have the \ref retain_e flag set to 0. */ dont = 0b0, - /// Application Messages keep the \ref retain_e flag they were published with. + /** Application Messages keep the \ref retain_e flag they were published with. */ retain = 0b1 }; @@ -98,17 +99,16 @@ struct subscribe_options { * when the subscription is established. */ enum class retain_handling_e : std::uint8_t { - /// Send retained messages at the time of subscribe. + /** Send retained messages at the time of subscribe. */ send = 0b00, - /// Send retained message only if the subscription does not currently exist. + /** Send retained message only if the subscription does not currently exist. */ new_subscription_only = 0b01, - /// Do not send retained messages at the time of subscribe. - not_send = 0b10 + /** Do not send retained messages at the time of subscribe. */ + not_send = 0b100 }; - //TODO: figure out how to properly link qos_e to link to its page /// Maximum \ref qos_e level at which the Server can send Application Messages to the Client. qos_e max_qos = qos_e::exactly_once; @@ -131,7 +131,7 @@ struct subscribe_topic { /// An UTF-8 Encoded String indicating the Topics to which the Client wants to subscribe. std::string topic_filter; - /// \ref subscribe_options associated with the subscription. + /// The \ref subscribe_options associated with the subscription. subscribe_options sub_opts; }; @@ -295,14 +295,35 @@ class will_props : public prop::properties< prop::user_property >{}; + +/** + * \brief Represents the Will Message. + * + * \details A Will Message is an Application Message that + * the Broker should publish after the Network Connection is closed + * in cases where the Network Connection is not closed normally. + */ class will : public will_props { std::string _topic; std::string _message; qos_e _qos; retain_e _retain; public: + /** + * \brief Constructs an empty Will Message. + */ will() = default; + /** + * \brief Construct a Will Message. + * + * \param topic Topic, identification of the information channel to which + * the Will Message will be published. + * \param message The message that will be published. + * \param qos The \ref qos_e level used when publishing the Will Message. + * \param retain The \ref retain_e flag specifying if the Will Message + * is to be retained when it is published. + */ will( std::string topic, std::string message, qos_e qos = qos_e::at_most_once, retain_e retain = retain_e::no @@ -311,6 +332,17 @@ public: _qos(qos), _retain(retain) {} + /** + * \brief Construct a Will Message. + * + * \param topic Topic name, identification of the information channel to which + * the Will Message will be published. + * \param message The message that will be published. + * \param qos The \ref qos_e level used when publishing the Will Message. + * \param retain The \ref retain_e flag specifying if the Will Message + * is to be retained when it is published. + * \param props Will properties. + */ will( std::string topic, std::string message, qos_e qos, retain_e retain, will_props props @@ -321,21 +353,34 @@ public: {} // just to make sure that we don't accidentally make a copy + /// Copy constructor. will(const will&) = delete; + + /// Move constructor. will(will&&) noexcept = default; + /// Copy assignment operator. will& operator=(const will&) = delete; + + /// Move assignment operator. will& operator=(will&&) noexcept = default; + /// Get the Topic Name. constexpr std::string_view topic() const { return _topic; } + + /// Get the Application Message. constexpr std::string_view message() const { return _message; } + + /// Get the \ref qos_e. constexpr qos_e qos() const { return _qos; } + + /// Get the \ref retain_e. constexpr retain_e retain() const { return _retain; }