Document LoggerType concept and improve Getting Started chapter

Summary:
related to T15252, T15261, T15263, #24

- documented LoggerType concept
- configuring the client chapter changed to getting started chapter with new additions:
	- code examples for each section (choosing underlying type, configuring the client, and using it)
	- added a secion on debugging the client using our logger implementation
- minor fixes related to reviewer's suggestions

Reviewers: ivica

Reviewed By: ivica

Subscribers: iljazovic, miljen

Differential Revision: https://repo.mireo.local/D32487
This commit is contained in:
Korina Šimičević
2024-11-29 09:53:34 +01:00
parent 67152be209
commit 319d024981
18 changed files with 235 additions and 75 deletions

View File

@ -37,6 +37,7 @@
[template mqttlink[id text][@https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc[id] [text]]]
[def __OPENSSL__ [@https://www.openssl.org/ OpenSSL]]
[def __HIVEMQ__ [@https://www.hivemq.com/ HiveMQ]]
[def __CompletionToken__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.completion_tokens_and_handlers CompletionToken]]
[def __Executor__ [@boost:/doc/html/boost_asio/reference/Executor1.html Executor]]
@ -44,6 +45,7 @@
[def __StreamType__ [reflink StreamType]]
[def __TlsContext__ [reflink TlsContext]]
[def __is_authenticator__ [reflink is_authenticator]]
[def __LoggerType__ [reflink LoggerType]]
[def __Boost__ [@https://www.boost.org/ Boost]]
[def __Asio__ [@boost:/libs/asio/index.html Boost.Asio]]
@ -58,6 +60,7 @@
[def __STRAND__ [@boost:doc/html/boost_asio/reference/io_context__strand.html `boost::asio::io_context::strand`]]
[def __DISPATCH__ [@boost:doc/html/boost_asio/reference/dispatch.html `boost::asio::dispatch`]]
[def __POST__ [@boost:doc/html/boost_asio/reference/post.html `boost::asio::post`]]
[def __ASYNC_IMMEDIATE__ [@https://www.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/async_immediate.html `boost::asio::async_immediate`]]
[def __CO_SPAWN__ [@boost:/doc/html/boost_asio/reference/co_spawn.html `boost::asio::co_spawn`]]
[def __USE_AWAITABLE__ [@boost:/doc/html/boost_asio/reference/use_awaitable.html `boost::asio::use_awaitable`]]
[def __USE_FUTURE__ [@boost:/doc/html/boost_asio/reference/use_future.html `boost::asio::use_future`]]
@ -125,16 +128,27 @@
[def __REASON_CODES__ [reflink2 Reason_codes `Reason Codes`]]
[def __ERROR_HANDLING__ [reflink2 Error_handling `Error handling`]]
[import ../../example/hello_world_over_tcp.cpp]
[import ../../example/hello_world_over_tls.cpp]
[import ../../example/hello_world_over_websocket_tcp.cpp]
[import ../../example/hello_world_over_websocket_tls.cpp]
[import ../../example/publisher.cpp]
[import ../../example/receiver.cpp]
[import ../../example/multiflight_client.cpp]
[import ../../example/timeout_with_parallel_group.cpp]
[import ../../example/timeout_with_awaitable_operators.cpp]
[import ../../example/hello_world_in_multithreaded_env.cpp]
[import ../../example/hello_world_in_coro_multithreaded_env.cpp]
[include 01_intro.qbk]
[include 02_configuring_the_client.qbk]
[include 02_getting_started.qbk]
[include 03_auto_reconnect.qbk]
[include 04_maintaining_a_stable_connection.qbk]
[include 05_optimising_communication.qbk]
[include 06_disconnecting_the_client.qbk]
[include 07_asio_compliance.qbk]
[include 11_multithreading.qbk]
[include 15_examples.qbk]
[include 12_examples.qbk]
[include examples/Examples.qbk]

View File

@ -4,7 +4,7 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:configuring_the_client Configuring the Client]
[section:getting_started Getting Started]
[nochunk]
This section guides you through the steps to properly configure the __Client__ to establish a connection with your chosen MQTT Broker.
@ -14,7 +14,7 @@ Instead, it features a function that will start the Client (see [refmem mqtt_cli
All configuration of the __Client__ must be finalised before invoking [refmem mqtt_client async_run].
Upon calling this function, the __Client__ makes its initial attempt to connect.
[section:transport_protocol Choosing a suitable transport protocol]
[section:transport_protocol Choosing a Suitable Transport Protocol]
The initial step is selecting an appropriate transport protocol for your MQTT connection.
@ -25,22 +25,18 @@ and WebSocket over TCP/IP and TLS/SSL.
MQTT Brokers come in various implementations and support different transport protocols.
Therefore, it is important to familiarise yourself with the protocols your chosen Broker supports.
Additionally, gather any necessary details such as certificate authority, client certificate, or private keys,
Additionally, gather any necessary details, such as certificate authority, client certificate, or private keys,
which might be required for establishing a secure connection.
The upcoming examples will demonstrate the configuration and the publishing of a "Hello World!" application message at `QoS` 0,
using various transport protocols:
In this example, we choose TCP/IP as the underlying protocol to initialize the __Client__.
* [link async_mqtt5.hello_world_over_tcp hello_world_over_tcp.cpp]
* [link async_mqtt5.hello_world_over_tls hello_world_over_tls.cpp]
* [link async_mqtt5.hello_world_over_websocket_tcp hello_world_over_websocket_tcp.cpp]
* [link async_mqtt5.hello_world_over_websocket_tls hello_world_over_websocket_tls.cpp]
[init_tcp_client]
[endsect] [/transport_protocol]
[section:customisation Customising your MQTT connection]
[section:configuration Configuring Your MQTT Connection]
The __Client__ offers a variety of functions for customising your MQTT connection settings.
The __Client__ offers a variety of functions for configuring your MQTT connection settings.
These functionalities include:
* *Specifying a list of Brokers:* You *must* use this function to assign a list of Brokers that the __Client__ will try to connect to (see [refmem mqtt_client brokers]).
@ -52,13 +48,22 @@ Listing Brokers from different clusters may lead to inconsistencies between MQTT
* *Assign a custom user-implemented authenticator:* The custom authentication will be used for __ENHANCED_AUTH__ ([refmem mqtt_client authenticator]).
* *Defining CONNECT Packet Properties:* Specify properties that will be included in the __CONNECT__ packet sent during connection initiation (see [refmem mqtt_client connect_property] and [refmem mqtt_client connect_properties]).
We will connect to the __HIVEMQ__'s public Broker at `broker.hivemq.com`, which listens for MQTT connections on the default TCP/IP port 1883.
Additionally, we will set the Client Identifier to `async_mqtt5_tester` using the [refmem mqtt_client credentials] function.
This is not strictly mandatory, as some Brokers allow anonymous connections.
After configuring the `mqtt_client`, we call the [refmem mqtt_client async_run] function.
This starts the process of establishing a connection with the Broker.
[configure_tcp_client]
It is important to note that these configurations apply to every Broker listed in [refmem mqtt_client brokers].
To modify any configuration parameters, you must first stop the __Client__ using [refmem mqtt_client cancel] or [refmem mqtt_client async_disconnect].
Afterwards, you can re-apply the configurations and restart the __Client__ with [refmem mqtt_client async_run].
[endsect] [/customisation]
[endsect] [/configuration]
[section:establishing_a_connection Establishing a connection]
[section:establishing_a_connection Establishing a Connection]
The __Client__ initiates a connection with the first Broker from the list of Brokers assigned using [refmem mqtt_client brokers].
A single attempt at connecting involves several steps:
@ -87,4 +92,41 @@ and `jitter` is a randomly chosen value between `-500ms` to `500ms`, intended to
[endsect] [/establishing_a_connection]
[endsect] [/configuring_the_client]
[section:using_the_client Using the Client]
After calling [refmem mqtt_client async_run], you can now use the Client according to your application needs.
In this case, we will publish a "Hello World!" message to `async-mqtt5/test` topic with Quality of Service 0 (at most once) using the [refmem mqtt_client async_publish] function.
[publish_hello_world]
You can find the full program listing for this chapter at the link below:
* [link async_mqtt5.hello_world_over_tcp hello_world_over_tcp.cpp]
Additional "Hello World!" examples for different underlying transport protocols can be found here:
* [link async_mqtt5.hello_world_over_tls hello_world_over_tls.cpp]
* [link async_mqtt5.hello_world_over_websocket_tcp hello_world_over_websocket_tcp.cpp]
* [link async_mqtt5.hello_world_over_websocket_tls hello_world_over_websocket_tls.cpp]
[endsect] [/using_the_client]
[section:debugging Debugging the Client]
If you encounter configuration or connection issues, you can use our logging mechanism to debug problems.
The __Client__ introduces a __LoggerType__ as its third template parameter, which specifies the type used for logging events within the __Client__.
The __Self__ library provides a built-in [ghreflink include/async_mqtt5/logger.hpp logger] implementation that outputs operation results to stderr.
This logger outputs detailed information about each step in the connection process, including DNS resolution, TCP connection, TLS handshake, WebSocket handshake, and MQTT handshake.
To enable this functionality, construct the __Client__ with an instance of this logger class:
[!c++]
// Since we are not establishing a secure connection, set the TlsContext template parameter to std::monostate.
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket, std::monostate /* TlsContext */, async_mqtt5::logger> client(
ioc, {} /* tls_context */, async_mqtt5::logger(async_mqtt5::log_level::debug)
);
[endsect] [/debugging]
[endsect] [/getting_started]

View File

@ -4,7 +4,7 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:auto_reconnect Built-in auto-reconnect and retry mechanism]
[section:auto_reconnect Built-in Auto-Reconnect and Retry Mechanism]
[nochunk]
The auto-reconnect and retry mechanism is a key feature of the __Self__ library.
@ -54,19 +54,19 @@ and [refmem mqtt_client async_disconnect]).
[endsect] [/sentry]
[section:cons Considerations and limitations]
[section:cons Considerations and Limitations]
The integrated auto-reconnect and retry mechanism greatly improves the user experience
by simplifying complex processes and ensuring continuous connections.
However, it is important to be mindful of certain limitations and considerations associated with this feature.
[heading Delayed handler invocation]
[heading Delayed Handler Invocation]
During extended periods of __Client__ downtime, the completion handlers for asynchronous functions,
such as those used in [refmem mqtt_client async_publish], may face considerable delays before invocation.
This can result in users being left in the dark regarding the status of their requests due to the absence of prompt feedback on the initiated actions.
[heading Concealing configuration-related issues]
[heading Concealing Configuration-Related Issues]
The __Client__ will always try to reconnect to the Broker(s) regardless of the reason why the connection was previously closed.
This is desirable behaviour when the connection gets dropped due to underlying stream transport issues,
@ -93,10 +93,10 @@ By design, one of the main functional requirements of the __Client__ was to hand
If the decision for reconnection were left to the user, then the user would need to handle all those error states manually,
which would dramatically increase the complexity of the user's code, not to mention how difficult it would be to cover all possible error states.
The proposed approach for detecting configuration errors in the __Client__ is to use some simple logging facility during development.
Log lines should be injected directly into the __Client__ code (typically in the connect_op.hpp file), and logs would uncover misconfigurations (if any).
The proposed approach for detecting configuration errors in the __Client__ is to use our logging mechanism as described
in [link async_mqtt5.getting_started.debugging Debugging the Client]
[heading Increased resource consumption]
[heading Increased Resource Consumption]
The __Client__ is designed to automatically buffer requests that are initiated while it is offline.
During extended downtime or when a high volume of requests accumulates, this can lead to an increase in memory usage.

View File

@ -4,7 +4,7 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:connection_maintenance Maintaining a stable connection]
[section:connection_maintenance Maintaining a Stable Connection]
[nochunk]
This chapter delves into the strategies used by the __Client__ to sustain a stable connection with the Broker.
@ -33,14 +33,14 @@ Use [refmem mqtt_client keep_alive] function during the __Client__ configuration
Otherwise, the __Client__ defaults to a `Keep Alive` period of `60 seconds`.
[note
The MQTT does not use the TCP's built-in keep-alive mechanism as it is inflexible and limited in that it can be configured solely at the operating system level.
The MQTT protocol does not use the TCP's built-in keep-alive mechanism as it is inflexible and limited in that it can be configured solely at the operating system level.
The default time a connection must be idle before sending the first keep-alive packet is typically set to 2 hours,
exceeding the tolerances of most MQTT applications.
]
[endsect] [/keep_alive]
[section:half_open_connections Detecting and handling half-open connections]
[section:half_open_connections Detecting and Handling Half-open Connections]
Ensuring the integrity and stability of network connections is a complex task,
given the number of potential disruptions such as software anomalies,

View File

@ -4,7 +4,7 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:optimising_communication Optimising communication]
[section:optimising_communication Optimising Communication]
[nochunk]
This chapter provides a detailed breakdown of how __Client__ optimises its communications with the Broker
@ -12,7 +12,7 @@ with multiflight mode for simultaneous message handling and strategies for effic
These techniques are key to getting the most out of MQTT in scenarios demanding fast and
dependable message delivery, all while meeting the protocol's quality of service requirements and network efficiency standards.
[section:multiflight The multiflight mode]
[section:multiflight The Multiflight Mode]
The __Self__ library introduces a multiflight feature.
This allows the initiation of multiple asynchronous requests simultaneously, without waiting for the completion of the previous requests.
@ -40,7 +40,7 @@ Source: [link async_mqtt5.multiflight_client multiflight_client.cpp]
[endsect] [/multiflight]
[section:packet_queuing Efficient bandwidth usage with packet queuing]
[section:packet_queuing Efficient Bandwidth Usage With Packet Queuing]
The __Client__ employs a strategic queuing mechanism crucial in optimising network usage and performance for the user's requests.
This mechanism bundles multiple MQTT packets for transmission within a single TCP packet whenever feasible
@ -62,7 +62,7 @@ if possible [footnote The Broker's `Receive Maximum` is equal to or greater than
[endsect] [/packet_queuing]
[section:packet_ordering Packet ordering]
[section:packet_ordering Packet Ordering]
The __Client__ uses a packet ordering mechanism to manage the queued packets pending dispatch to the Broker.
The most important ordering rules are:

View File

@ -90,14 +90,13 @@ In this case, the proper way to disconnect would be to call [refmem mqtt_client
);
```
[section:reusing_the_client Restarting the Client after disconnection]
[section:reusing_the_client Restarting the Client After Disconnection]
Once the __Client__ has been successfully stopped, reactivating it is straightforward and requires invoking [refmem mqtt_client async_run].
This method can be called right after initiating [refmem mqtt_client async_disconnect], without waiting for it to complete.
The __Client__ is configurable again in the interval between stopping and restarting.
See `Customising your MQTT connection` in [link async_mqtt5.configuring_the_client Configuring the Client]
for more information.
See [link async_mqtt5.getting_started.configuration Configuring Your MQTT Connection] for more information.
```
int main() {

View File

@ -4,7 +4,7 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:asio_compliance Compliance with Boost.Asio]
[section:asio_compliance Compliance With Boost.Asio]
Every asynchronous operation in __Asio__ has associated characteristics that specify their behaviour.

View File

@ -4,13 +4,13 @@
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:multithreading Using the mqtt_client in a multithreaded environment]
[section:multithreading Using the mqtt_client in a Multithreaded Environment]
[nochunk]
This chapter provides information about thread safety of the __Client__ and other __Asio__-compliant objects
and provides examples of how to write thread-safe code in multithreaded environments.
[section:thread_safety Thread safety of ASIO-compliant objects]
[section:thread_safety Thread Safety of ASIO-Compliant Objects]
A common misconception exists regarding the "thread safety" of ASIO-compliant asynchronous objects,
specifically around the belief that initialising such an object with a __STRAND__
@ -37,7 +37,7 @@ Instead, it encourages developers to implement their own concurrency management
[endsect] [/thread_safety]
[section:executors_threads_strands Executors, threads, and strands]
[section:executors_threads_strands Executors, Threads, and Strands]
Before delving into thread-safe programming, it is essential to understand the distinction between executors and threads.
Executors are not threads but mechanisms for scheduling how and when work gets done.
@ -56,7 +56,7 @@ Refer to __ASIO_STRANDS__ for more details.
[endsect] [/executors_threads_strands]
[section:thread_safe_code Writing thread-safe code]
[section:thread_safe_code Writing Thread-Safe Code]
As mentioned previously, it is the user's responsibility to ensure that none of the __Client__'s member functions
are called concurrently from separate threads.

View File

@ -8,25 +8,21 @@
[section:hello_world_over_tcp Hello World over TCP/IP]
This example illustrates the process of setting up the Client to connect to the Broker via TCP/IP and publish a "Hello World!" message.
[import ../../../example/hello_world_over_tcp.cpp]
[hello_world_over_tcp]
[endsect] [/hello_world_over_tcp]
[section:hello_world_over_tls Hello World over TLS/SSL]
This example illustrates the process of setting up the Client to connect to the Broker via TLS/SSL and publish a "Hello World!" message.
[import ../../../example/hello_world_over_tls.cpp]
[hello_world_over_tls]
[endsect] [/hello_world_over_tls]
[section:hello_world_over_websocket_tcp Hello World over Websocket/TCP]
This example illustrates the process of setting up the Client to connect to the Broker via Websocket/TCP and publish a "Hello World!" message.
[import ../../../example/hello_world_over_websocket_tcp.cpp]
[hello_world_over_websocket_tcp]
[endsect] [/hello_world_over_websocket_tcp]
[section:hello_world_over_websocket_tls Hello World over Websocket/TLS]
This example illustrates the process of setting up the Client to connect to the Broker via Websocket/TLS and publish a "Hello World!" message.
[import ../../../example/hello_world_over_websocket_tls.cpp]
[hello_world_over_websocket_tls]
[endsect] [/hello_world_over_websocket_tls]
@ -34,7 +30,6 @@ This example illustrates the process of setting up the Client to connect to the
This example shows how to use __Client__ as a publisher that publishes sensor readings every `5` seconds.
The __Client__ uses TCP to connect to the Broker and modified __USE_AWAITABLE__ as the completion token.
[import ../../../example/publisher.cpp]
[publisher]
[endsect]
@ -43,14 +38,12 @@ This example shows how to use __Client__ as a receiver.
The __Client__ subscribes and indefinitely receives Application Messages from the Broker.
The __Client__ uses TCP to connect to the Broker and modified __USE_AWAITABLE__ as the completion token.
[import ../../../example/receiver.cpp]
[receiver]
[endsect]
[section:multiflight_client The multiflight Client]
This example shows how to use __Client__ to simultaneously dispatch multiple requests.
[import ../../../example/multiflight_client.cpp]
[multiflight_client]
[endsect]
@ -59,7 +52,6 @@ This example demonstrates how to use the __Client__ with its support for per-ope
using parallel group.
Specifically, in this example, the __Client__ will subscribe to a Topic and try to receive a message from the Topic within `5 seconds`.
[import ../../../example/timeout_with_parallel_group.cpp]
[timeout_with_parallel_group]
[endsect]
@ -69,21 +61,18 @@ using awaitable operators.
Specifically, in this example, a call to [refmem mqtt_client async_publish] and [refmem mqtt_client async_disconnect] must complete
within `5 seconds`. Otherwise, they will be cancelled.
[import ../../../example/timeout_with_awaitable_operators.cpp]
[timeout_with_awaitable_operators]
[endsect]
[section:hello_world_in_multithreaded_env Hello World in a multithreaded environment using callbacks]
This example demonstrates how to publish a "Hello World" message in a multithreaded environment using callbacks (`post`/`dispatch`).
[import ../../../example/hello_world_in_multithreaded_env.cpp]
[hello_world_in_multithreaded_env]
[endsect]
[section:hello_world_in_coro_multithreaded_env Hello World in a multithreaded environment using coroutines]
This example demonstrates how to publish a "Hello World" message in a multithreaded environment using coroutines (`co_spawn`).
[import ../../../example/hello_world_in_coro_multithreaded_env.cpp]
[hello_world_in_coro_multithreaded_env]
[endsect]

View File

@ -0,0 +1,87 @@
[/
Copyright (c) 2023-2024 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:LoggerType LoggerType concept]
`LoggerType` represents an object type that will be used by the __Client__ to log events.
A type satisfies the `LoggerType` concept if it defines [*any number (including zero)] of the following functions:
[table:log_functions
[[Function signature] [Arguments] [Description]]
[
[`void at_resolve(error_code ec, std::string_view host, std::string_view port, const asio::ip::tcp::resolver::results_type& eps);`]
[
[*`ec`] is the `error_code` returned by the resolve operation.
[*`host`] is the hostname used in the resolve.
[*`port`] is the port used in the resolve.
[*`eps`] is a list of endpoints returned by the resolve operation.
]
[Invoked when the resolve operation is complete.]
]
[
[`void at_tcp_connect(error_code ec, asio::ip::tcp::endpoint ep);`]
[
[*`ec`] is the `error_code` returned by the TCP connect operation.
[*`ep`] is a TCP endpoint used to establish the TCP connection.
]
[Invoked when the TCP connect operation is complete.]
]
[
[`void at_tls_handshake(error_code ec, asio::ip::tcp::endpoint ep);`]
[
[*`ec`] is the `error_code` returned by the the TLS handshake operation.
[*`ep`] is a TCP endpoint used to establish the TLS handshake.
]
[Invoked when the TLS handshake operation is complete.]
]
[
[`void at_ws_handshake(error_code ec, asio::ip::tcp::endpoint ep);`]
[
[*`ec`] is the `error_code` returned by the the WebSocket handshake operation.
[*`ep`] is a TCP endpoint used to establish the WebSocket handshake.
]
[Invoked when the WebSocket handshake operation is complete.]
]
[
[`void at_connack(reason_code rc, bool session_present, const connack_props& ca_props);`]
[
[*`rc`] is the `reason_code` received in the __CONNACK__ packet indicating the result of the MQTT handshake.
[*`session_present`] A flag indicating whether the Broker already has a session associated with this connection.
[*`ca_props`] __CONNACK_PROPS__ received in the __CONNACK__ packet.
]
[Invoked when the __CONNACK__ packet is received, marking the completion of the MQTT handshake. ]
]
[
[`void at_disconnect(reason_code rc, const disconnect_props& dc_props);`]
[
[*`rc`] is the `reason_code` received in the __DISCONNECT__ packet specifying the reason behind the disconnection.
[*`dc_props`] __DISCONNECT_PROPS__ received in the __DISCONNECT__ packet.
]
[Invoked when the __DISCONNECT__ packet is received, indicating that the Broker wants to close this connection. ]
]
]
For example, a type `T` that defines `at_connack` and `at_disconnect` functions with their respective arguments is considered a valid `LoggerType`.
This allows you to create your own `LoggerType` classes with functions of interest.
All defined functions are invoked directly within the __Client__ using its default executor.
If the __Client__ is initialized with an explicit or implicit strand, none of the functions will be invoked concurrently.
[warning Defined functions should not block and stop the __Client__ from doing work. ]
A class that satifies this concept is [ghreflink include/async_mqtt5/logger.hpp logger].
[endsect]

View File

@ -20,7 +20,6 @@
<member><link linkend="async_mqtt5.ref.subscribe_options">subscribe_options</link></member>
<member><link linkend="async_mqtt5.ref.subscribe_topic">subscribe_topic</link></member>
<member><link linkend="async_mqtt5.ref.will">will</link></member>
<member><link linkend="async_mqtt5.ref.logger">logger</link></member>
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
@ -42,7 +41,6 @@
<member><link linkend="async_mqtt5.ref.disconnect_rc_e">disconnect_rc_e</link></member>
<member><link linkend="async_mqtt5.ref.qos_e">qos_e</link></member>
<member><link linkend="async_mqtt5.ref.retain_e">retain_e</link></member>
<member><link linkend="async_mqtt5.ref.log_level">log_level</link></member>
</simplelist>
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
@ -75,6 +73,12 @@
<member><link linkend="async_mqtt5.ref.Reason_codes">Reason codes</link></member>
<member><link linkend="async_mqtt5.ref.Error_handling">Error handling</link></member>
</simplelist>
<bridgehead renderas="sect3">Logging</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="async_mqtt5.ref.LoggerType">LoggerType</link></member>
<member><link linkend="async_mqtt5.ref.logger">logger</link></member>
<member><link linkend="async_mqtt5.ref.log_level">log_level</link></member>
</simplelist>
</entry>
</row></tbody>
</tgroup>

View File

@ -31,6 +31,7 @@
[include concepts/StreamType.qbk]
[include concepts/TlsContext.qbk]
[include concepts/is_authenticator.qbk]
[include concepts/LoggerType.qbk]
[include reason_codes/Reason_codes.qbk]
[include properties/will_props.qbk]
[include properties/connect_props.qbk]
@ -1470,10 +1471,12 @@
<xsl:when test="contains($qualified-name, 'StreamType')">StreamType</xsl:when>
<xsl:when test="contains($qualified-name, 'TlsContext')">TlsContext</xsl:when>
<xsl:when test="contains($qualified-name, 'is_authenticator')">is_authenticator</xsl:when>
<xsl:when test="contains($qualified-name, 'LoggerType')">LoggerType</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="string-length($template-type) &gt; 0">
<xsl:choose>
<xsl:when test="string-length($template-type) &gt; 0">
<xsl:value-of select="substring-before($qualified-name, $template-type)"/>
<xsl:text>__</xsl:text><xsl:value-of select="$template-type"/><xsl:text>__</xsl:text>
<xsl:value-of select="substring-after($qualified-name, $template-type)"/>
@ -1481,7 +1484,11 @@
<xsl:text> </xsl:text>
<xsl:value-of select="declname"/>
</xsl:if>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$qualified-name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="mqtt-ref-id">
@ -1524,7 +1531,8 @@
or contains(type, 'ExecutionContext')
or contains(type, 'TlsContext')
or contains(type, 'StreamType')
or contains(type, 'is_authenticator')">
or contains(type, 'is_authenticator')
or contains(type, 'LoggerType')">
<xsl:call-template name="mqtt-template">
<xsl:with-param name="qualified-name" select="$type"/>
</xsl:call-template>

View File

@ -15,23 +15,36 @@
#include <async_mqtt5.hpp>
int main() {
//[init_tcp_client
// Initialize the execution context required to run I/O operations.
boost::asio::io_context ioc;
// Construct the Client with ``__TCP_SOCKET__`` as the underlying stream.
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
//async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket, std::monostate /* TlsContext */, async_mqtt5::logger> client(
ioc, {} /* tls_context */, async_mqtt5::logger(async_mqtt5::log_level::debug)
);
//]
//[configure_tcp_client
// 1883 is the default TCP MQTT port.
client.brokers("broker.hivemq.com", 1883)
.credentials("async_mqtt5_tester")
.async_run(boost::asio::detached);
//]
//[publish_hello_world
client.async_publish<async_mqtt5::qos_e::at_most_once>(
"async-mqtt5/test", "Hello world!",
async_mqtt5::retain_e::yes, async_mqtt5::publish_props {},
[&client](async_mqtt5::error_code ec) {
std::cout << ec.message() << std::endl;
// Disconnnect the Client.
client.async_disconnect(boost::asio::detached);
}
);
//]
ioc.run();
}

View File

@ -130,7 +130,7 @@ public:
write_prefix();
std::clog
<< "tls handshake: "
<< "TLS handshake: "
<< ep.address().to_string() << ":" << ep.port()
<< " - " << ec.message()
<< std::endl;
@ -148,7 +148,7 @@ public:
write_prefix();
std::clog
<< "ws handshake: "
<< "WebSocket handshake: "
<< ep.address().to_string() << ":" << ep.port()
<< " - " << ec.message()
<< std::endl;

View File

@ -41,6 +41,7 @@ namespace asio = boost::asio;
* 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.
* \tparam \__LoggerType\__ Type of object used to log events within the Client.
*
* \par Thread safety
* ['Distinct objects]: safe. \n
@ -85,7 +86,7 @@ public:
*
* \param ex An executor that will be associated with the Client.
* \param tls_context A context object used in TLS/SSL connection.
* \param logger An object used to log events within the Client.
* \param logger An object satisfying the \__LoggerType\__ concept used to log events within the Client.
*/
explicit mqtt_client(
const executor_type& ex,
@ -102,7 +103,7 @@ public:
* \tparam \__ExecutionContext\__ Type of a concrete execution context.
* \param context Execution context whose executor will be associated with the Client.
* \param tls_context A context object used in TLS/SSL connection.
* \param logger An object used to log events within the Client.
* \param logger An object satisfying the \__LoggerType\__ concept used to log events within the Client.
*
* \par Precondition
* \code
@ -442,7 +443,7 @@ public:
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
* equivalent to using \__ASYNC_IMMEDIATE\__.
*
* \par Handler signature
* The handler signature for this operation depends on the \ref qos_e specified:\n
@ -535,7 +536,7 @@ public:
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
* equivalent to using \__ASYNC_IMMEDIATE\__.
*
* \par Handler signature
* The handler signature for this operation:
@ -608,7 +609,7 @@ public:
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
* equivalent to using \__ASYNC_IMMEDIATE\__.
*
* \par Handler signature
* The handler signature for this operation:
@ -677,7 +678,7 @@ public:
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
* equivalent to using \__ASYNC_IMMEDIATE\__.
*
* \par Handler signature
* The handler signature for this operation:
@ -745,7 +746,7 @@ public:
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
* equivalent to using \__ASYNC_IMMEDIATE\__.
*
* \par Handler signature
* The handler signature for this operation:
@ -871,8 +872,6 @@ public:
* \param props An instance of \__DISCONNECT_PROPS\__.
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
*
* \par Handler signature
* The handler signature for this operation:
@ -935,8 +934,6 @@ public:
*
* \param token Completion token that will be used to produce a
* completion handler. The handler will be invoked when the operation completes.
* On immediate completion, invocation of the handler will be performed in a manner
* equivalent to using \__POST\__.
*
* \par Handler signature
* The handler signature for this operation:

View File

@ -25,7 +25,14 @@ using error_code = boost::system::error_code;
* such as the hostname, port, and path.
*/
struct authority_path {
std::string host, port, path;
/** The hostname of the authority as a domain name or an IP address. */
std::string host;
/** The port number used for communication. */
std::string port;
/** Specifies the endpoint path relevant to WebSocket connections. */
std::string path;
};
/**

View File

@ -115,8 +115,8 @@ BOOST_AUTO_TEST_CASE(successful_connect_debug) {
BOOST_TEST_MESSAGE(log);
BOOST_TEST_WARN(contains(log, "resolve"));
BOOST_TEST_WARN(contains(log, "connect"));
BOOST_TEST_WARN(contains(log, "tls handshake"));
BOOST_TEST_WARN(contains(log, "ws handshake"));
BOOST_TEST_WARN(contains(log, "TLS handshake"));
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
BOOST_TEST_WARN(contains(log, "connack"));
}