diff --git a/doc/qbk/01_intro.qbk b/doc/qbk/01_intro.qbk index a2a74ab..0619315 100644 --- a/doc/qbk/01_intro.qbk +++ b/doc/qbk/01_intro.qbk @@ -1,45 +1,111 @@ [section:intro Introduction] [nochunk] -__Self__ is a C++ client for the __MQTT__ protocol, based on __Asio__. +__Self__ is a C++20 client built on Boost.Asio. +This client is designed for publishing or receiving messages from an MQTT 5.0 compatible broker. +__Self__ represents a comprehensive implementation of the MQTT 5.0 protocol standard, +offering full support for publishing or receiving messages with QoS 0, 1, and 2. [heading Motivation] +The __MQTT__ protocol is widely utilised for communication in various real-world scenarios, +primarily serving as a reliable communication protocol for data transfer to and from IoT devices. +While the MQTT protocol itself is relatively straightforward, integrating it into an application can be complex, +especially due to the challenging implementation of message retransmission after a disconnect/reconnect sequence. -[...motivation here...] +The aim of __Self__ is to provide a very simple asynchronous C++ interface for application developers. +The internal client's implementation manages network and MQTT protocol details. +Notably, the client does not expose connect functions (nor asynchronous connect functions); +instead, network connectivity, MQTT handshake, and message retransmission are automatically handled within the client. -The design goals of this library are: +The __Self__ interface aligns seamlessly with the __Asio__ asynchronous model. +The client's asynchronous functions are compatible with all completion tokens supported by __Asio__. -* reason 1 -* reason 2 -* ... +[heading Features] +__Self__ is a C++ MQTT Client library designed with the core belief that users should focus solely on their application logic, not the network complexities. [br] +The library attempts to embody this belief with a range of key features designed to elevate the development experience: -Non-goals: +* [*Complete TCP, TLS/SLL, and WebSocket support] +* [*User-focused simplicity]: Providing an interface that is as simple as possible without compromising functionality. +* [*Prioritized efficiency]: Utilising network and memory resources as efficiently as possible. +* [*Minimal memory footprint]: Ensuring optimal performance in resource-constrained environments typical of IoT devices. +* [*Automatic reconnect]: Automatically attempt to re-establish a connection in the event of a disconnection. +* [*Fully Boost.Asio compliant]: The interfaces and implementation strategies are built upon the foundations of __Asio__. [br] +__Asio__ and __Beast__ users will have no issues understanding and integrating __Self__. [br] +Furthermore, __Self__ integrates well with any other library within the Boost.Asio ecosystem. +* [*Custom allocators]: Support for custom allocators allows extra flexibility and control over the memory resources. [br] +__Self__ will use allocators associated with handlers from asynchronous functions to create instances of objects needed in the library implementation. +* [*Per-Operation Cancellation]: All asynchronous operations support individual, targeted cancellation as per Asio’s __ASIO_PER_OP_CANCELLATION__. +* [*Completion Token]: All asynchronous functions support __CompletionToken__, allowing for versatile usage with callbacks, coroutines, futures, and more. +* [*Full implementation of MQTT 5.0 specification] +* [*Support for QoS 0, QoS 1, and QoS 2] +* [*Custom authentication]: __Self__ defines an interface for your own custom authenticators to perform Enhanced Authentication. +* [*High availability]: __Self__ supports listing multiple Brokers within the same cluster to which the Client can connect. [br] +In the event of a connection failure with one Broker, the Client switches to the next in the list. +* [*Offline buffering]: While offline, it automatically buffers all the packets to send when the connection is re-established. -* reason 1 -* reason 2 -* ... +[heading Example] +The following example illustrates a simple scenario of configuring a Client and publishing an Application Message. + +[!c++] + #include + + #include + #include + + #include + + int main() { + boost::asio::io_context ioc; + using client_type = async_mqtt5::mqtt_client; + client_type c(ioc, ""); + + c.credentials("clientid", "", "") + .brokers("mqtt.broker", 1883) + .run(); + + c.async_publish( + "test/mqtt-test", "hello world with qos0!", + async_mqtt5::retain_e::no, async_mqtt5::publish_props {}, + [](async_mqtt5::error_code ec) { + std::cout << ec.message() << std::endl; + } + ); + + ioc.run(); + } + +To see more examples, visit [link async_mqtt5.examples Examples]. [heading When to use] -If any of the following statements is true, you may consider using __Self__: +__Self__ might be suitable for you if any of the following statements is true: -* reason 1 -* reason 2 -* ... +* Your application uses __Asio__ and requires integrating a MQTT Client. +* You require asynchronous access to an MQTT Broker. +* You are developing a higher-level component that requires a connection to an MQTT Broker. +* You require a dependable and resilient MQTT Client that can automatically manage all network-related issues. -It may not be a good fit for you if: +It may not be suitable for you if: -* reason 1 -* reason 2 -* ... +* You solely require synchronous access to an MQTT Broker. +* The MQTT Broker you are connecting to does not support the MQTT 5 version. +[heading Requirements] -[heading Tested compilers and systems] +__Self__ is a header-only library. +To use __Self__ it requires the following: -[...some text here...] +* [*C++20] capable compiler. +* [*Boost 1.82 or later]. In addition to Asio, we use other header-only libraries such as Beast, Spirit, and more. +* [*OpenSSL]. Only if you require an SSL connection by using [asioreflink ssl__stream ssl::stream]. + +__Self__ has been tested with the following compilers: + +* clang 14.0 (Linux) +* MSVC 14.3 - Visual Studio 2022 (Windows) [heading Acknowledgements] - -[...some acknowledgements here...] +We thank [@https://github.com/chriskohlhoff Christopher Kohlhoff] for his outstanding __Asio__ library, +which inspired the design of all interfaces and implementation strategies. [endsect] [/intro] diff --git a/doc/qbk/02_examples.qbk b/doc/qbk/02_examples.qbk index 77f7305..b255550 100644 --- a/doc/qbk/02_examples.qbk +++ b/doc/qbk/02_examples.qbk @@ -6,29 +6,21 @@ ] [section:examples Examples] -The main class in __Self__ is __Client__, and the upcoming sections will briefly explain how to use it. +The following examples demonstrate how to use __Client__ in different scenarios. -The first two examples will demonstrate using __Client__ as a publisher and receiver. - -* [link async_mqtt5.examples.publisher The publisher] -* [link async_mqtt5.examples.receiver The receiver] - -The following two sections serve as reference. The first section will show how to use different underlying transport protocols (such as TCP, SSL and WebSocket) -to establish a connection to an MQTT Broker. +to establish a connection to a MQTT Broker. * [link async_mqtt5.examples.network_connection Establishing a network connection with different protocols] -The second section will showcase how to use asynchronous functions in __Client__ -with different completion tokens. +The second section will showcase how to use asynchronous functions in __Client__ +with different __CompletionToken__. * [link async_mqtt5.examples.asio Compatibility with Boost.Asio] * [link async_mqtt5.examples.asio.callbacks Async functions with callbacks] * [link async_mqtt5.examples.asio.cpp20_coroutines Async functions with C++20 coroutines] * [link async_mqtt5.examples.asio.futures Async functions with futures] - - -[include examples/Basic_examples.qbk] + [include examples/Network_connection.qbk] [include examples/Asio_compatibility.qbk] diff --git a/doc/qbk/examples/Asio_compatibility.qbk b/doc/qbk/examples/Asio_compatibility.qbk index 130dae9..0c17403 100644 --- a/doc/qbk/examples/Asio_compatibility.qbk +++ b/doc/qbk/examples/Asio_compatibility.qbk @@ -6,8 +6,8 @@ ] [section:asio Compatibility with Boost.Asio] -The __Self__ is built upon __Asio__ and thus follows the same principles. -This section illustrates the usage of __Self__ async +The __Client__ is built upon __Asio__ and thus follows the same principles. +This section illustrates the usage of __Client__ async functions with different __CompletionToken__. # [link async_mqtt5.examples.asio.callbacks Async functions with callbacks] @@ -16,14 +16,14 @@ functions with different __CompletionToken__. [section:callbacks Async functions with callbacks] -This example demonstrates how to use __Self__ asynchrous functions with callbacks. +This example demonstrates how to use __Client__ asynchrous functions with callbacks. [import ../../../example/callbacks.cpp] [callbacks_examples] [endsect] [section:cpp20_coroutines Async functions with C++20 coroutines] -This example demonstrates how to use __Self__ asynchrous functions with C++20 coroutines +This example demonstrates how to use __Client__ asynchrous functions with C++20 coroutines using __USE_AWAITABLE__ and __CO_SPAWN__. [import ../../../example/cpp20_coroutines.cpp] @@ -31,7 +31,7 @@ using __USE_AWAITABLE__ and __CO_SPAWN__. [endsect] [section:futures Async functions with futures] -This example demonstrates how to use __Self__ asynchrous functions with __USE_FUTURE__ +This example demonstrates how to use __Client__ asynchrous functions with __USE_FUTURE__ completion token. [import ../../../example/futures.cpp] [futures_examples] diff --git a/doc/qbk/examples/Basic_examples.qbk b/doc/qbk/examples/Basic_examples.qbk deleted file mode 100644 index 23f4166..0000000 --- a/doc/qbk/examples/Basic_examples.qbk +++ /dev/null @@ -1,17 +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) -] - -[import ../../../example/basic_examples.cpp] - -[section:publisher The publisher] -[publisher] -[endsect] - -[section:receiver The receiver] - -[endsect] - diff --git a/doc/qbk/examples/Network_connection.qbk b/doc/qbk/examples/Network_connection.qbk index 4039b32..ead5491 100644 --- a/doc/qbk/examples/Network_connection.qbk +++ b/doc/qbk/examples/Network_connection.qbk @@ -15,12 +15,12 @@ transport protocols such as TCP/IP, TLS/SSL, and WebSocket. [import ../../../example/network_connection.cpp] [h3 TCP/IP connection] -To create a TCP/IP connection with a Broker, initialise __Self__ with __TCP_SOCKET__ as the __StreamType__. +To create a TCP/IP connection with a Broker, initialize __Client__ with __TCP_SOCKET__ as the __StreamType__. [tcp] [h3 TLS/SSL connection] To establish a secure and encrypted connection using the TLS/SSL protocol, supply a context object that meets the __TlsContext__ requirements. -Additionally, initialise __Self__ with an underlying stream that implements TLS/SSL protocol as the __StreamType__. +Additionally, initialize __Client__ with an underlying stream that implements TLS/SSL protocol as the __StreamType__. This example will demonstrate how to set up an SSL connection using __SSL_CONTEXT__ and __SSL_STREAM__. To use SSL support in __Asio__, __OPENSSL__ is required. @@ -38,6 +38,6 @@ __WEBSOCKET_STREAM__. [h4 WebSocket over TLS/SSL] [websocket_tls] -Once the __Client___ has been initialised with a suitable __StreamType__, it is prepared for configuration and utilisation. +Once the __Client__ has been initialized with a suitable __StreamType__, it is prepared for configuration and utilization. [endsect] diff --git a/example/basic_examples.cpp b/example/basic_examples.cpp deleted file mode 100644 index 9a4313a..0000000 --- a/example/basic_examples.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//[basic_examples - - -//[publisher -#include - -#include -#include - -#include - -namespace asio = boost::asio; - -void client_publisher() { - // Initialise execution context. - asio::io_context ioc; - - // Initialise the ``__Client__``, establish connection to the Broker over TCP. - async_mqtt5::mqtt_client client (ioc.get_executor(), ""); - client.brokers("mqtt.broker", 1883) // Broker that we want to connect to. 1883 is the default TCP port. - .run(); // Start the client. - - client.async_publish( - "topic", "my application message", - async_mqtt5::retain_e::yes, async_mqtt5::publish_props {}, - [](async_mqtt5::error_code ec, async_mqtt5::reason_code rc, async_mqtt5::puback_props props) { - if (ec) - std::cout << "An application error occurred: " << ec.message() << std::endl; - if (rc) - std::cout << "MQTT protocol error occurred: " << rc.message() << std::endl; - } - ); - - // Publish some more messages... - - // After we are done with publishing all the messages, disconnect the client. - // You can also use mqtt_client::cancel. - // Either way, you should make sure all the operations completed before disconnecting the client! - client.async_disconnect( - async_mqtt5::disconnect_rc_e::normal_disconnection, async_mqtt5::disconnect_props {}, - [](async_mqtt5::error_code ec) { - if (ec) - std::cout << "An error during disconnect occurred: " << ec.message() << std::endl; - }); - - // Start the execution. - ioc.run(); -} - -//] - - -//] \ No newline at end of file