[mqtt-client] documentation setup

Summary: related to T12804

Reviewers: ivica

Reviewed By: ivica

Subscribers: miljen

Differential Revision: https://repo.mireo.local/D26026
This commit is contained in:
Korina Šimičević
2023-10-13 09:07:56 +02:00
parent 83493c83d9
commit 3d3f7aeb94
13 changed files with 1042 additions and 14 deletions

124
doc/Jamfile Normal file
View File

@@ -0,0 +1,124 @@
project async_mqtt5/doc ;
import boostbook ;
import quickbook ;
import os ;
local BOOST_ROOT = [ os.environ BOOST_ROOT ] ;
# echo $(BOOST_ROOT) ;
# unfortunately, it can only import docca.jam in relative path format
import ../../../../../../../../d/boost_1_82_0/tools/docca/docca.jam ;
local doxygen_exclussions =
detail
impl
;
docca.reference reference.qbk
:
xsl/custom-overrides.xsl
[ glob-tree-ex ../include/async_mqtt5/ : *.hpp : $(doxygen_exclussions) ]
:
<doxygen:param>PROJECT_NAME=async_mqtt5
<doxygen:param>PROJECT_BRIEF="MQTT C++ Client Library"
<doxygen:param>DISTRIBUTE_GROUP_DOC=YES
<doxygen:param>ENABLE_PREPROCESSING=YES
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>SEARCH_INCLUDES=NO
<doxygen:param>"PREDEFINED=\\
\"BOOST_ASIO_INITFN_RESULT_TYPE(t,a)=auto\" \\
\"BOOST_ASIO_COMPLETION_TOKEN_FOR(sig)=class\" \\
\"BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct,sig)=auto\" \\
\"BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(ex)=\" \\
\"BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(ex)=\" \\
\"protected=private\" \\
\"BOOST_CXX14_CONSTEXPR=constexpr\" \\
"
<doxygen:param>SKIP_FUNCTION_MACROS=NO
<doxygen:param>OUTPUT_LANGUAGE=English
<doxygen:param>INLINE_INHERITED_MEMB=YES
<doxygen:param>AUTOLINK_SUPPORT=NO
<doxgen:param>BRIEF_MEMBER_DESC=NO
<doxygen:param>EXTRACT_ALL=YES
<doxygen:param>HAVE_DOT=NO
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>HIDE_UNDOC_CLASSES=YES
<doxygen:param>HIDE_FRIEND_COMPOUNDS=YES
<doxygen:param>CASE_SENSE_NAMES=YES
<doxygen:param>SHOW_INCLUDE_FILES=NO
<doxygen:param>INLINE_INFO=NO
<doxygen:param>SORT_MEMBER_DOCS=NO
<doxygen:param>SORT_MEMBERS_CTORS_1ST=YES
<doxygen:param>SHOW_USED_FILES=NO
<doxygen:param>SHOW_FILES=NO
<doxygen:param>SHOW_NAMESPACES=NO
<doxygen:param>QUIET=NO
;
install stylesheets
:
$(BOOST_ROOT)/doc/src/boostbook.css
:
<location>html/
;
explicit stylesheets ;
install callouts
:
[ glob $(BOOST_ROOT)/doc/src/images/callouts/*.png ]
:
<location>html/images/callouts
;
explicit callout ;
install images
:
[ glob $(BOOST_ROOT)/doc/src/images/*.png ]
:
<location>html/images
;
explicit images ;
xml async_mqtt5_doc
:
qbk/00_main.qbk
:
<dependency>reference.qbk
<dependency>images
;
explicit async_mqtt5_doc ;
boostbook async_mqtt5
:
async_mqtt5_doc
:
<xsl:param>"boost.root=https://www.boost.org/doc/libs/1_82_0"
<xsl:param>boost.graphics.root=images/
<xsl:param>nav.layout=none
<xsl:param>chapter.autolabel=1
<xsl:param>chunk.section.depth=8
<xsl:param>chunk.first.sections=1
<xsl:param>toc.section.depth=8
<xsl:param>toc.max.depth=8
<xsl:param>generate.toc="chapter toc,title section nop reference nop part toc"
<xsl:param>html.stylesheet=boostbook.css
<include>$(BOOST_ROOT)tools/boostbook/dtd
:
<dependency>stylesheets
<dependency>images
;
# These are used to inform the build system of the
# means to build the integrated and stand-alone docs.
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : async_mqtt5 ;
explicit boostrelease ;

53
doc/qbk/00_main.qbk Normal file
View File

@@ -0,0 +1,53 @@
[library async_mqtt5
[quickbook 1.7]
[copyright 2023 Mireo]
[id async_mqtt5]
[purpose MQTT C++ client library]
[license
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])
]
[authors [A,B,C]]
[category template]
[category generic]
]
[template nochunk[] [block '''<?dbhtml stop-chunking?>''']]
[template mdash[] '''&mdash; ''']
[template include_file[path][^<'''<ulink url="GITHUB_LINK">'''[path]'''</ulink>'''>]]
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[template reflink2[id text][link async_mqtt5.ref.async_mqtt5__[id] [^[text]]]]
[template reflink[id][reflink2 [id] [id]]]
[template refmem[class mem][reflink2 [class].[mem] [class]::[mem]]]
[template refmemunq[class mem][reflink2 [class].[mem] [mem]]]
[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]]]
[def __ExecutionContext__ [reflink2 ExecutionContext ['ExecutionContext]]]
[def __StreamType__ [reflink2 StreamType ['StreamType]]]
[def __TlsContext__ [reflink2 TlsContext ['TlsContext]]]
[def __Boost__ [@https://www.boost.org/ Boost]]
[def __Asio__ [@boost:/libs/asio/index.html Boost.Asio]]
[def __Self__ [async_mqtt5]]
[/ MQTT stuff]
[def __MQTT__ [@https://mqtt.org/ MQTT]]
[include 01_intro.qbk]
[section:ref Reference]
[xinclude helpers/quickref.xml]
[block'''<part label="Two: Reference">''']
[include reference.qbk]
[include helpers/ExecutionContext.qbk]
[include helpers/StreamType.qbk]
[include helpers/TlsContext.qbk]
[include helpers/Reason_codes.qbk]
[block'''</part>''']
[endsect]

45
doc/qbk/01_intro.qbk Normal file
View File

@@ -0,0 +1,45 @@
[section:intro Introduction]
[nochunk]
__Self__ is a C++ client for the __MQTT__ protocol, based on __Asio__.
[heading Motivation]
[...motivation here...]
The design goals of this library are:
* reason 1
* reason 2
* ...
Non-goals:
* reason 1
* reason 2
* ...
[heading When to use]
If any of the following statements is true, you may consider using __Self__:
* reason 1
* reason 2
* ...
It may not be a good fit for you if:
* reason 1
* reason 2
* ...
[heading Tested compilers and systems]
[...some text here...]
[heading Acknowledgements]
[...some acknowledgements here...]
[endsect] [/intro]

View File

@@ -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__ExecutionContext ExecutionContext concept]
`ExecutionContext` represents a place where function objects will be executed.
`ExecutionContext` type must be convertible to [asioreflink execution_context execution_context] which
is a base class for concrete execution context types.
The [asioreflink io_context io_context] type is an example of a derived type.
[endsect]

View File

@@ -0,0 +1,114 @@
[/
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]

View File

@@ -0,0 +1,23 @@
[/
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__StreamType StreamType concept]
`StreamType` represents the transport protocol type used to transfer stream of bytes.
`StreamType` should meet the [beastconceptslink streams Stream] 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&`.
The `lowest_layer_type` should inherit from [asioreflink basic_stream_socket basic_stream_socket].
The types [asioreflink basic_stream_socket basic_stream_socket<Protocol, Executor>],
[asioreflink ssl__stream ssl::stream<Stream>], and
[beastreflink boost__beast__websocket__stream websocket::stream<NextLayer>]
meet these requirements.
[endsect]

View File

@@ -0,0 +1,14 @@
[/
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__TlsContext TlsContext concept]
// TODO
The type [asioreflink ssl__context ssl::context] meets these requirements.
[endsect]

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
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)
-->
<informaltable frame="all">
<tgroup cols="4">
<colspec colname="a"/><colspec colname="b"/><colspec colname="c"/><colspec colname="d"/>
<tbody><row>
<entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__authority_path">authority_path</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__mqtt_client">mqtt_client</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_code">reason_code</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__subscribe_options">subscribe_options</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__subscribe_topic">subscribe_topic</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__will">will</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Type aliases</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__error_code">error_code</link></member>
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__ExecutionContext">ExecutionContext</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__StreamType">StreamType</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__TlsContext">TlsContext</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Enumerations</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__client__error">client_error</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__disconnect_rc_e">disconnect_rc_e</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__qos_e">qos_e</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__retain_e">retain_e</link></member>
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<member><link linkend="async_mqtt5.ref.async_mqtt5__Reason_codes">Reason codes</link></member>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__client__get_error_code_category">get_error_code_category</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__client__make_error_code">make_error_code</link></member>
</simplelist>
</entry>
</row></tbody>
</tgroup>
</informaltable>

75
doc/qbk/helpers/rcref.xml Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
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)
-->
<informaltable frame="all">
<tgroup cols="3">
<colspec colname="a"/><colspec colname="b"/><colspec colname="c"/>
<tbody><row>
<entry valign="top">
<bridgehead renderas="sect3">Success</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__success">success</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__normal_disconnection">normal_disconnection</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__granted_qos_0">granted_qos_0</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__granted_qos_1">granted_qos_1</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__granted_qos_2">granted_qos_2</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__disconnect_with_will_message">disconnect_with_will_message</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__no_matching_subscribers">no_matching_subscribers</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__no_subscription_existed">no_subscription_existed</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__continue_authentication">continue_authentication</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Error</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__unspecified_error">unspecified_error</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__malformed_packet">malformed_packet</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__protocol_error">protocol_error</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__implementation_specific_error">implementation_specific_error</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__unsupported_protocol_version">unsupported_protocol_version</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__client_id_not_valid">client_id_not_valid</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__bad_username_or_password">bad_username_or_password</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__not_authorized">not_authorized</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__server_unavailable">server_unavailable</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__server_busy">server_busy</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__banned">banned</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__server_shutting_down">server_shutting_down</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__bad_authentication_method">bad_authentication_method</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__keep_alive_timeout">keep_alive_timeout</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__session_taken_over">session_taken_over</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__topic_filter_invalid">topic_filter_invalid</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__topic_name_invalid">topic_name_invalid</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__packet_id_in_use">packet_id_in_use</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__packet_id_not_found">packet_id_not_found</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__receive_maximum_exceeded">receive_maximum_exceeded</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__topic_alias_invalid">topic_alias_invalid</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__packet_too_large">packet_too_large</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__message_rate_too_high">message_rate_too_high</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__quota_exceeded">quota_exceeded</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__administrative_action">administrative_action</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__payload_format_invalid">payload_format_invalid</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__retain_not_supported">retain_not_supported</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__qos_not_supported">qos_not_supported</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__use_another_server">use_another_server</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__server_moved">server_moved</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__shared_subscriptions_not_supported">shared_subscriptions_not_supported</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__connection_rate_exceeded">connection_rate_exceeded</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__maximum_connect_time">maximum_connect_time</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__subscription_ids_not_supported">subscription_ids_not_supported</link></member>
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__wildcard_subscriptions_not_supported">wildcard_subscriptions_not_supported</link></member>
</simplelist>
<bridgehead renderas="sect3">Special</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.async_mqtt5__reason_codes__empty">empty</link></member>
</simplelist>
</entry>
</row></tbody>
</tgroup>
</informaltable>

View File

@@ -0,0 +1,37 @@
<!--
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)
-->
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" expand-text="yes">
<xsl:variable name="doc-ns" select="'async_mqtt5'"/>
<xsl:variable name="doc-ref" select="'async_mqtt5.ref'"/>
<xsl:variable name="debug" select="0"/>
<xsl:variable name="private" select="0"/>
<xsl:variable name="include-private-members" select="false()"/>
<xsl:template mode="includes-template-footer" match="location">
<xsl:variable name="convenience-header" as="xs:string?">
<xsl:apply-templates mode="convenience-header" select="@file"/>
</xsl:variable>
<xsl:if test="$convenience-header">
<xsl:text>{$nl}</xsl:text>
<xsl:text>Convenience header [include_file {$convenience-header}]</xsl:text>
<xsl:text>{$nl}</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template mode="convenience-header" match="@file[contains(., 'async_mqtt5')]">async_mqtt5.hpp</xsl:template>
<xsl:variable name="emphasized-template-parameter-types" select="
'ExecutionContext',
'StreamType',
'TlsContext'
"/>
</xsl:stylesheet>

View File

@@ -7,11 +7,21 @@
#include <boost/asio/error.hpp>
namespace async_mqtt5 {
/**
* \brief A representation of Disconnect Reason Code.
*
* \details Represents all Reason Codes that the Client can send to the Server
* 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.
normal_disconnection = 0x00,
/// 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
unspecified_error = 0x80,
malformed_packet = 0x81,
protocol_error = 0x82,
@@ -27,18 +37,35 @@ enum class disconnect_rc_e : std::uint8_t {
};
namespace client {
/**
* \brief MQTT client error codes.
*
* \details Represents error that occur on the client side.
*/
enum class error : int {
/// [unused] A fatal error occurred.
fatal_error = 100,
/// Malformed packet has been detected.
malformed_packet,
/// There are no more available Packet Identifiers to use.
pid_overrun,
/// [unused] The Client has reconnected.
reconnected,
/// The Client has been disconnected.
disconnected,
// publish
// publish
/// The Server does not support the specified \ref qos_e.
qos_not_supported,
/// 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.
topic_alias_maximum_reached
};
@@ -50,9 +77,9 @@ inline std::string client_error_to_string(error err) {
case fatal_error:
return "A fatal error occurred";
case malformed_packet:
return "Malformed packet has been received";
return "Malformed packet has been detected";
case pid_overrun:
return "Ran out of the available packet ids to use";
return "There are no more available Packet Identifiers to use.";
case reconnected:
return "The Client has reconnected";
case disconnected:
@@ -100,11 +127,21 @@ enum class category : uint8_t {
} // end namespace reason_codes
/**
* \brief A class holding Reason Code values originating from Control Packets.
*
* \details A Reason Code is a one byte unsigned value that indicates the result of an operation.
* Reason Codes less than 0x80 indicate successful completion of an operation.
* The normal Reason Code for success is 0.
* Reason Code values of 0x80 or greater indicate failure.
* The CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, DISCONNECT and AUTH Control Packets have a single Reason Code as part of the Variable Header.
* The SUBACK and UNSUBACK packets contain a list of one or more Reason Codes in the Payload.
*/
class reason_code {
uint8_t _code;
reason_codes::category _category { reason_codes::category::none };
public:
/// @cond INTERNAL
constexpr reason_code() : _code(0xff) {}
constexpr reason_code(uint8_t code, reason_codes::category cat)
@@ -112,31 +149,49 @@ public:
{}
constexpr reason_code(uint8_t code) : _code(code) {}
/// @endcond
/// Copy constructor.
reason_code(const reason_code&) = default;
/// Move constructor.
reason_code(reason_code&&) = default;
/**
* \brief Indication if the object holds a Reason Code indicating an error.
*
* \details Any Reason Code holding a value equal or greater than 0x80.
*/
explicit operator bool() const noexcept {
return _code >= 0x80;
}
/**
* \brief Returns the byte value of the Reason Code.
*/
constexpr uint8_t value() const noexcept {
return _code;
}
/// Insertion operator.
friend std::ostream& operator<<(std::ostream& os, const reason_code& rc) {
os << rc.message();
return os;
}
/// Operator less than.
friend bool operator<(const reason_code& lhs, const reason_code& rhs) {
return lhs._code < rhs._code;
}
/// Equality operator.
friend bool operator==(const reason_code& lhs, const reason_code& rhs) {
return lhs._code == rhs._code && lhs._category == rhs._category;
}
/**
* \brief Returns a message describing the meaning behind the Reason Code.
*/
std::string message() const {
switch (_code) {
case 0x00:

View File

@@ -16,12 +16,21 @@ namespace async_mqtt5 {
namespace asio = boost::asio;
/**
* \brief MQTT client used to connect and communicate with a Broker.
*
* \tparam StreamType Type of the underlying transport protocol used to transfer
* the stream of bytes between the Client and the Broker. The transport must be
* ordered and lossless.
* \tparam TlsContext Type of the context object used in TLS/SSL connections.
*/
template <
typename StreamType,
typename TlsContext = std::monostate
>
class mqtt_client {
public:
/// The executor type associated with the client.
using executor_type = typename StreamType::executor_type;
private:
using stream_type = StreamType;
@@ -36,7 +45,13 @@ private:
clisvc_ptr _svc_ptr;
public:
/**
* \brief Constructs a Client with given parameters.
*
* \param ex An executor that will be associated with the Client.
* \param cnf
* \param tls_context A context object used in TLS/SLL connection.
*/
explicit mqtt_client(
const executor_type& ex,
const std::string& cnf,
@@ -47,6 +62,17 @@ public:
))
{}
/**
* \brief Constructs a client with given parameters.
*
* \tparam ExecutionContext Type of a concrete execution context.
* \param context Execution context whose executor will be associated with the Client.
* \param cnf
* \param tls_context A context object used in TLS/SLL connection.
*
* \par Precondition
* `std::is_convertible_v<ExecutionContext&, asio::execution_context&>`
*/
template <typename ExecutionContext>
requires (std::is_convertible_v<ExecutionContext&, asio::execution_context&>)
explicit mqtt_client(
@@ -57,19 +83,37 @@ public:
mqtt_client(context.get_executor(), cnf, std::move(tls_context))
{}
/**
* \brief Destructor.
*
* \details Automatically calls \ref mqtt_client::cancel.
*/
~mqtt_client() {
cancel();
}
/**
* \brief Get the executor associated with the object.
*/
executor_type get_executor() const noexcept {
return _svc_ptr->get_executor();
}
/**
* \brief Get the context object used in TLS/SSL connection.
*
* \par Precondition
* `!std::is_same_v<TlsContext, std::monostate>`.
*/
decltype(auto) tls_context()
requires (!std::is_same_v<TlsContext, std::monostate>) {
return _svc_ptr->tls_context();
}
/**
* \brief Start the Client.
*/
void run() {
_svc_ptr->open_stream();
detail::ping_op { _svc_ptr }
@@ -78,17 +122,34 @@ public:
detail::sentry_op { _svc_ptr }.perform();
}
// TODO: channel cancel
/**
* \brief Cancel all asynchronous operations.
*
* \details All outstanding operations will complete with `boost::asio::error::operation_aborted`.
*/
void cancel() {
get_executor().execute([svc_ptr = _svc_ptr]() {
svc_ptr->cancel();
});
}
/**
* \brief Assign a \ref will Message.
*
* \details The \ref will Message that will be published after the Network Connection is closed.
*/
mqtt_client& will(will will) {
_svc_ptr->will(std::move(will));
return *this;
}
/**
* \brief Assign credentials that will be used to connect to a Broker.
*
* \details Credentials consist of a unique Client Identifier and, optionally,
* a User Name and Password.
*/
mqtt_client& credentials(
std::string client_id,
std::string username = "", std::string password = ""
@@ -100,11 +161,76 @@ public:
return *this;
}
/**
* \brief Assign a list of Brokers that the Client will attempt to connect to.
*
* \param hosts List of Broker addresses and ports.
* Address and ports are separated with a colon `:` while
* pairs of addresses and ports are separated with a comma `,`.
* \param default_port Default port to connect to in case the port is not
* explicitly specified in the hosts list.
*
* \details Examples of a valid hosts string:\n
* - broker1:1883, broker2, broker3:1883\n
* - broker1
*/
mqtt_client& brokers(std::string hosts, uint16_t default_port = 1883) {
_svc_ptr->brokers(std::move(hosts), default_port);
return *this;
}
// TODO: doc props
/**
* \brief Send a PUBLISH packet to Broker to transport an
* Application Message.
*
* \tparam qos_type The \ref qos_e level of assurance for delivery.
* \param topic Identification of the information channel to which
* Payload data is published.
* \param payload The Application Message that is being published.
* \param retain The \ref retain_e flag.
* \param props PUBLISH properties.
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation depends on the \ref qos_e specified:\n
*
* - `qos_e::at_most_once`:
* \code
* void (
* boost::system::error_code // Result of operation
* )
* \endcode
*
* - `qos_e::at_least_once`:
* \code
* void (
* boost::system::error_code, // Result of operation.
* async_mqtt5::reason_code, // Reason Code received from Broker.
* puback_props // Properties received in the PUBACK packet.
* )
* \endcode
*
* - `qos_e::exactly_once`:
* \code
* void (
* boost::system::error_code, // Result of operation.
* async_mqtt5::reason_code, // Reason Code received from Broker.
* pubcomp_props // Properties received in the PUBCOMP packet.
* )
* \endcode
*
* \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::operation_aborted` \n
* - \link client::error::pid_overrun \endlink
* - \link client::error::qos_not_supported \endlink
* - \link client::error::retain_not_available \endlink
* - \link client::error::topic_alias_maximum_reached \endlink
*/
template <qos_e qos_type, typename CompletionToken>
decltype(auto) async_publish(
std::string topic, std::string payload,
@@ -133,6 +259,39 @@ public:
);
}
// TODO: perhaps there is a way to not copy documentation (\copybrief, \copydetails)
/**
* \brief Send a SUBSCRIBE packet to Broker to create a subscription
* to one or more Topics of interest.
*
* \details After the subscription has been established, the Broker will send
* PUBLISH packets to the Client to forward Application Messages that were published
* to Topics that the Client subscribed to. The PUBLISH packets can be received
* with \ref mqtt_client::async_receive function.
*
* \param topics A list of \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.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code, // Result of operation.
* std::vector<reason_code>, // Vector of Reason Codes indicating
* // the subscription result for each Topic
* // in the SUBSCRIBE packet.
* suback_props, // Properties received in the SUBACK packet.
* )
* \endcode
*
* \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::operation_aborted` \n
* - \link client::error::pid_overrun \endlink
*/
template <typename CompletionToken>
decltype(auto) async_subscribe(
const std::vector<subscribe_topic>& topics,
@@ -156,6 +315,38 @@ public:
);
}
/**
* \brief Send a SUBSCRIBE packet to Broker to create a subscription
* to one Topics of interest.
*
* \details After the subscription has been established, the Broker will send
* PUBLISH packets to the Client to forward Application Messages that were published
* 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 props SUBSCRIBE properties.
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code, // Result of operation.
* std::vector<reason_code>, // Vector of Reason Codes containing the
* // single subscription result for the Topic
* // in the SUBSCRIBE packet.
* suback_props, // Properties received in the SUBACK packet.
* )
* \endcode
*
* \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::operation_aborted` \n
* - \link client::error::pid_overrun \endlink
*/
template <typename CompletionToken>
decltype(auto) async_subscribe(
const subscribe_topic& topic, const subscribe_props& props,
@@ -167,6 +358,38 @@ public:
);
}
/**
* \brief Send an UNSUBSCRIBE packet to Broker to unsubscribe from one
* or more Topics.
*
* \note The Client MAY receive PUBLISH packets with Application
* Messages from Topics the Client just unsubscribed to if
* they were buffered for delivery on the Broker side beforehand.
*
* \param topics List of Topics to unsubscribe from.
* \param props UNSUBSCRIBE properties.
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code, // Result of operation.
* std::vector<reason_code>, // Vector of Reason Codes indicating
* // the result of unsubscribe operation
* // for each Topic in the UNSUBSCRIBE packet.
* unsuback_props, // Properties received in the UNSUBACK packet.
* )
* \endcode
*
* \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::operation_aborted` \n
* - \link client::error::pid_overrun \endlink
*/
template <typename CompletionToken>
decltype(auto) async_unsubscribe(
const std::vector<std::string>& topics, const unsubscribe_props& props,
@@ -190,6 +413,37 @@ public:
);
}
/**
* \brief Send an UNSUBSCRIBE packet to Broker to unsubscribe
* from one Topic.
*
* \note The Client MAY receive PUBLISH packets with Application
* Messages from Topics the Client just unsubscribed to if
* they were buffered for delivery on the Broker side beforehand.
*
* \param topic Topic to unsubscribe from.
* \param props UNSUBSCRIBE properties.
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code, // Result of operation.
* std::vector<reason_code>, // Vector of Reason Codes containing
* // the result of unsubscribe operation
* // for the Topic in the UNSUBSCRIBE packet.
* unsuback_props, // Properties received in the UNSUBACK packet.
* )
* \endcode
*
* \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::operation_aborted` \n
* - \link client::error::pid_overrun \endlink
*/
template <typename CompletionToken>
decltype(auto) async_unsubscribe(
const std::string& topic, const unsubscribe_props& props,
@@ -201,6 +455,37 @@ public:
);
}
/**
* \brief Asynchronously receive an Application Message.
*
* \details The Client will receive and complete deliveries for all the
* PUBLISH packets received from the Broker throughout its lifetime.
* The Client will store them internally in order they were delivered.
* Calling this function will attempt to receive an Application Message
* from internal storage.
*
* \note The completion handler will be only invoked if an error occurred
* or there is a pending Application Message.
*
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code, // Result of operation.
* std::string, // Topic, the origin of the Application Message.
* std::string, // Payload, the content of the Application Message.
* publish_props, // Properties received in the PUBLISH packet.
* )
* \endcode
*
* \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::experimental::error::channel_cancelled`
*/
template <typename CompletionToken>
decltype(auto) async_receive(CompletionToken&& token) {
// Sig = void (error_code, std::string, std::string, publish_props)
@@ -209,6 +494,33 @@ public:
);
}
/**
* \brief Disconnect the Client.
*
* \details Send a DISCONNECT packet to the Broker with a Reason Code
* describing the reason for disconnection.
*
* \note This function has terminal effects and will close the Client.
*
* \param reason_code Reason Code to notify
* the Broker of the reason for disconnection.
* \param props DISCONNECT properties.
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code // Result of operation.
* )
* \endcode
*
* \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?
*/
template <typename CompletionToken>
decltype(auto) async_disconnect(
disconnect_rc_e reason_code, const disconnect_props& props,
@@ -220,6 +532,31 @@ public:
);
}
/**
* \brief Disconnect the Client.
*
* \details Send a DISCONNECT packet to the Broker with a Reason Code
* \ref reason_codes::normal_disconnection describing
* the reason for disconnection.
*
* \note This function has terminal effects and will close the Client.
*
* \param token Completion token that will be used to produce a
* completion handler, which will be called when the operation completed.
*
* \par Completion signature
* The completion signature for this operation:
* \code
* void (
* boost::system::error_code // Result of operation.
* )
* \endcode
*
* \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?
*/
template <typename CompletionToken>
decltype(auto) async_disconnect(CompletionToken&& token) {
return async_disconnect(

View File

@@ -11,52 +11,127 @@
namespace async_mqtt5 {
/// An alias for `boost::system::error_code`;
using error_code = boost::system::error_code;
struct authority_path {
std::string host, port, path;
};
/**
* \brief Represents the Quality of Service (QoS) property of the PUBLISH packets.
*
* \details Determines how the PUBLISH packets are delivered from the sender
* to the receiver.
*/
enum class qos_e : std::uint8_t {
/// 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.
at_least_once = 0b01,
/// All messages arrive at the receiver exactly once without
/// loss or duplication of the messages.
exactly_once = 0b10
};
/**
* \brief Represents the RETAIN flag in the PUBLISH packets.
*
* \details This flag informs the Server about whether or not it should
* store the current message.
*/
enum class retain_e : std::uint8_t {
yes = 0b1, no = 0b0,
/// 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.
no = 0b0
};
// TODO: should this be moved to internal types?
enum class dup_e : std::uint8_t {
yes = 0b1, no = 0b0,
yes = 0b1, no = 0b0
};
/**
* \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
* will be forwarded to a connection with a ClientID equal to the ClientID of the
* publishing connection.
*/
enum class no_local_e : std::uint8_t {
/// Application Messages can be forwarded to a connection with equal ClientID.
no = 0b0,
yes = 0b1,
/// Application Messages MUST NOT be forwarded to a connection with equal ClientID.
yes = 0b1
};
/**
* \brief Representation of the Retain As Published Subscribe Option.
*
* \details A Subscribe Option indicating whether or not Application Messages forwarded
* 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.
dont = 0b0,
retain = 0b1,
/// Application Messages keep the \ref retain_e flag they were published with.
retain = 0b1
};
/**
* \brief Representation of the Retain Handling Subscribe Option.
*
* \details A Subscribe Option specifying whether retained messages are sent
* when the subscription is established.
*/
enum class retain_handling_e : std::uint8_t {
/// Send retained messages at the time of subscribe.
send = 0b00,
/// Send retained message only if the subscription does not currently exist.
new_subscription_only = 0b01,
not_send = 0b10,
/// Do not send retained messages at the time of subscribe.
not_send = 0b10
};
//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;
/// Option determining if Application Messages will be forwarded to a connection with an equal ClientID.
no_local_e no_local = no_local_e::yes;
/// Option determining if Application Message will keep their \ref retain_e flag.
retain_as_published_e retain_as_published = retain_as_published_e::retain;
/// Option determining if retained messages are sent when the subscription is established.
retain_handling_e retain_handling = retain_handling_e::new_subscription_only;
};
/**
* \brief A representation of a Topic Subscription consisting of a Topic Filter and
* Subscribe Options.
*/
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.
subscribe_options sub_opts;
};