Update examples, tests & docs

Summary: related to T13242

Reviewers: ivica

Reviewed By: ivica

Subscribers: miljen, iljazovic

Differential Revision: https://repo.mireo.local/D26889
This commit is contained in:
Korina Šimičević
2023-12-07 15:41:31 +01:00
parent e0a0bafbf1
commit 0d778c6b59
15 changed files with 274 additions and 168 deletions

View File

@ -1,6 +1,6 @@
Async.MQTT5: A C++20 MQTT client based on Boost.Asio Async.MQTT5: A ~~C++20~~ C++17 MQTT client based on Boost.Asio
=============================== ===============================
Async.MQTT5 is a professional, industrial-grade C++20 client built on [Boost.Asio](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio.html). This client is designed for publishing or receiving messages from an MQTT 5.0 compatible broker. Async.MQTT5 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. Async.MQTT5 is a professional, industrial-grade C++17 client built on [Boost.Asio](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio.html). This client is designed for publishing or receiving messages from an MQTT 5.0 compatible broker. Async.MQTT5 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.
Our clear intention is to include the Async.MQTT5 library into [Boost](https://www.boost.org/). We are actively working on it. Our clear intention is to include the Async.MQTT5 library into [Boost](https://www.boost.org/). We are actively working on it.
@ -42,7 +42,7 @@ Using the library
You can compile the example below with the following command line on Linux: You can compile the example below with the following command line on Linux:
$ clang++ -std=c++20 <source-cpp-file> -o example -I<path-to-boost> -Iinclude -pthread $ clang++ -std=c++17 <source-cpp-file> -o example -I<path-to-boost> -Iinclude -pthread
Usage and API Usage and API
--------- ---------
@ -101,7 +101,7 @@ It may not be suitable for you if:
Requirements Requirements
--------- ---------
Async.MQTT5 is a header-only library. To use Async.MQTT5 it requires the following: Async.MQTT5 is a header-only library. To use Async.MQTT5 it requires the following:
- **C++20 capable compiler** - **C++17 capable compiler**
- **Boost 1.82 or later**. In addition to Asio, we use other header-only libraries such as Beast, Spirit, and more. - **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 [boost::asio::ssl::stream](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/reference/ssl__stream.html). - **OpenSSL**. Only if you require an SSL connection by using [boost::asio::ssl::stream](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/reference/ssl__stream.html).

View File

@ -1,7 +1,7 @@
[section:intro Introduction] [section:intro Introduction]
[nochunk] [nochunk]
__Self__ is a C++20 client built on __Asio__. __Self__ is a C++17 client built on __Asio__.
This client is designed for publishing or receiving messages from an MQTT 5.0 compatible broker. 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, __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. offering full support for publishing or receiving messages with QoS 0, 1, and 2.
@ -96,7 +96,7 @@ It may not be suitable for you if:
__Self__ is a header-only library. __Self__ is a header-only library.
To use __Self__ it requires the following: To use __Self__ it requires the following:
* [*C++20 capable compiler] * [*C++17 capable compiler]
* [*Boost 1.82 or later]. In addition to Asio, we use other header-only libraries such as Beast, Spirit, and more. * [*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]. * [*OpenSSL]. Only if you require an SSL connection by using [asioreflink ssl__stream ssl::stream].

View File

@ -95,7 +95,7 @@ int main(int argc, char** argv) {
client_type c(ioc.get_executor(), ""); client_type c(ioc.get_executor(), "");
c.credentials("test-client", "", "") c.credentials("test-client", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("mqtt.broker", 1883)
.run(); .run();
for (int i = 0; i < thread_num - 1; ++i) for (int i = 0; i < thread_num - 1; ++i)

View File

@ -1,10 +1,7 @@
#include <iostream> #include <iostream>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/ssl.hpp> #include <boost/asio/ssl.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/as_tuple.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
@ -14,7 +11,6 @@ namespace asio = boost::asio;
namespace async_mqtt5 { namespace async_mqtt5 {
constexpr auto use_nothrow_awaitable = asio::as_tuple(asio::use_awaitable);
template <typename StreamBase> template <typename StreamBase>
struct tls_handshake_type<asio::ssl::stream<StreamBase>> { struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
@ -33,27 +29,26 @@ void assign_tls_sni(
} // end namespace async_mqtt5 } // end namespace async_mqtt5
constexpr char spacetime_ca[] = constexpr char mireo_ca[] =
"-----BEGIN CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\n"
"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\n"
"Qz9m6w==\n"
"-----END CERTIFICATE-----\n" "-----END CERTIFICATE-----\n"
; ;
@ -66,14 +61,14 @@ void publish_qos0_openssl_tls() {
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec; error_code ec;
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos0-openssl-tls", "", "") c.credentials("test-qos0-openssl-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8883) .brokers("emqtt.mireo.local", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -99,14 +94,14 @@ void publish_qos1_openssl_tls() {
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec; error_code ec;
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos1-openssl-tls", "", "") c.credentials("test-qos1-openssl-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8883) .brokers("emqtt.mireo.local", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -134,14 +129,14 @@ void publish_qos2_openssl_tls() {
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec; error_code ec;
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos2-openssl-tls", "", "") c.credentials("test-qos2-openssl-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8883) .brokers("emqtt.mireo.local", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -169,14 +164,14 @@ void subscribe_and_receive_openssl_tls(int num_receive) {
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec; error_code ec;
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-subscriber-openssl-tls", "", "") c.credentials("test-subscriber-openssl-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8883) .brokers("emqtt.mireo.local", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -225,61 +220,9 @@ void subscribe_and_receive_openssl_tls(int num_receive) {
return; return;
} }
void test_coro() {
std::cout << "[Test-coro-openssl-tls]" << std::endl;
using namespace async_mqtt5;
asio::io_context ioc;
co_spawn(ioc, [&ioc]() -> asio::awaitable<void> {
using stream_type = asio::ssl::stream<asio::ip::tcp::socket>;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec;
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context));
c.credentials("coro-client", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run();
std::vector<subscribe_topic> topics;
topics.push_back(subscribe_topic {
"test/mqtt-test", {
qos_e::exactly_once,
subscribe_options::no_local_e::no,
subscribe_options::retain_as_published_e::retain,
subscribe_options::retain_handling_e::send
}
});
auto [ec1, codes, props] = co_await c.async_subscribe(
topics, subscribe_props {}, use_nothrow_awaitable
);
std::cout << "subscribe reason_code: " << codes[0].message() << std::endl;
auto [ec2, topic, payload, rec_props] = co_await c.async_receive(use_nothrow_awaitable);
std::cout << "topic: " << topic << std::endl;
std::cout << "payload: " << payload << std::endl;
asio::steady_timer timer(ioc);
timer.expires_from_now(std::chrono::seconds(1));
co_await timer.async_wait(use_nothrow_awaitable);
co_await c.async_disconnect(use_nothrow_awaitable);
co_return;
}, asio::detached);
ioc.run();
}
void run_openssl_tls_examples() { void run_openssl_tls_examples() {
publish_qos0_openssl_tls(); publish_qos0_openssl_tls();
publish_qos1_openssl_tls(); publish_qos1_openssl_tls();
publish_qos2_openssl_tls(); publish_qos2_openssl_tls();
subscribe_and_receive_openssl_tls(1); subscribe_and_receive_openssl_tls(1);
test_coro();
} }

View File

@ -20,7 +20,7 @@ asio::awaitable<void> client_publisher(asio::io_context& ioc) {
// Configure the ``__Client__``. // Configure the ``__Client__``.
// It is mandatory to call brokers() and run() to configure the Brokers to connect to and start the Client. // It is mandatory to call brokers() and run() to configure the Brokers to connect to and start the Client.
client.brokers("mqtt.mireo.local", 1883) // Broker that we want to connect to. 1883 is the default TCP port. client.brokers("mqtt.broker", 1883) // Broker that we want to connect to. 1883 is the default TCP port.
.run(); // Start the client. .run(); // Start the client.
// Publish an Application Message with QoS 1. // Publish an Application Message with QoS 1.

View File

@ -18,7 +18,7 @@ void publish_qos0_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos0-tcp", "", "") c.credentials("test-qos0-tcp", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("emqtt.mireo.local", 1883)
.will({ "test/mqtt-test", "Client disconnected!",qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!",qos_e::at_least_once })
.run(); .run();
@ -31,6 +31,7 @@ void publish_qos0_tcp() {
} }
); );
ioc.run(); ioc.run();
} }
@ -45,7 +46,7 @@ void publish_qos1_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos1-tcp", "", "") c.credentials("test-qos1-tcp", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("emqtt.mireo.local", 1883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -72,7 +73,7 @@ void publish_qos2_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos2-tcp", "", "") c.credentials("test-qos2-tcp", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("emqtt.mireo.local", 1883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -100,7 +101,7 @@ void subscribe_and_receive_tcp(int num_receive) {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-subscriber-tcp", "", "") c.credentials("test-subscriber-tcp", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("emqtt.mireo.local", 1883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();

View File

@ -23,12 +23,12 @@ void publish_qos0_websocket_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos0-websocket-tcp", "", "") c.credentials("test-qos0-websocket-tcp", "", "")
.brokers("fcluster-5/mqtt", 8083) .brokers("emqtt.mireo.local/mqtt", 8083)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
c.async_publish<qos_e::at_most_once>( c.async_publish<qos_e::at_most_once>(
"test/mqtt-test", "hello world with qos0!", "test/mqtt-test", "hello world with qos0!",
retain_e::no, publish_props{}, retain_e::no, publish_props{},
[&c](error_code ec) { [&c](error_code ec) {
std::cout << "error_code: " << ec.message() << std::endl; std::cout << "error_code: " << ec.message() << std::endl;
@ -53,7 +53,7 @@ void publish_qos1_websocket_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos1-websocket-tcp", "", "") c.credentials("test-qos1-websocket-tcp", "", "")
.brokers("fcluster-5/mqtt", 8083) .brokers("emqtt.mireo.local/mqtt", 8083)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -84,7 +84,7 @@ void publish_qos2_websocket_tcp() {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-qos2-websocket-tcp", "", "") c.credentials("test-qos2-websocket-tcp", "", "")
.brokers("fcluster-5/mqtt", 8083) .brokers("emqtt.mireo.local/mqtt", 8083)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -116,7 +116,7 @@ void subscribe_and_receive_websocket_tcp(int num_receive) {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("test-subscriber-websocket-tcp", "", "") c.credentials("test-subscriber-websocket-tcp", "", "")
.brokers("fcluster-5/mqtt", 8083) .brokers("emqtt.mireo.local/mqtt", 8083)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();

View File

@ -42,28 +42,26 @@ void assign_tls_sni(
} }
} // end namespace async_mqtt5 } // end namespace async_mqtt5
constexpr char mireo_ca[] =
constexpr const char spacetime_ca[] =
"-----BEGIN CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\n"
"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\n"
"Qz9m6w==\n"
"-----END CERTIFICATE-----\n" "-----END CERTIFICATE-----\n"
; ;
@ -78,14 +76,14 @@ void publish_qos0_websocket_tls() {
error_code ec; error_code ec;
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos0-websocket-tls", "", "") c.credentials("test-qos0-websocket-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8884) .brokers("emqtt.mireo.local/mqtt", 8884)
.will({ "test/mqtt-test", "Client disconnected!", async_mqtt5::qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", async_mqtt5::qos_e::at_least_once })
.run(); .run();
@ -113,14 +111,14 @@ void publish_qos1_websocket_tls() {
error_code ec; error_code ec;
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos1-websocket-tls", "", "") c.credentials("test-qos1-websocket-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8884) .brokers("emqtt.mireo.local/mqtt", 8884)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -149,14 +147,14 @@ void publish_qos2_websocket_tls() {
error_code ec; error_code ec;
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-qos2-websocket-tls", "", "") c.credentials("test-qos2-websocket-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8884) .brokers("emqtt.mireo.local/mqtt", 8884)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
@ -186,14 +184,14 @@ void subscribe_and_receive_websocket_tls(int num_receive) {
error_code ec; error_code ec;
asio::ssl::context tls_context(asio::ssl::context::tls_client); asio::ssl::context tls_context(asio::ssl::context::tls_client);
tls_context.add_certificate_authority(asio::buffer(spacetime_ca), ec); tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer); tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>; using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context)); client_type c(ioc, "", std::move(tls_context));
c.credentials("test-subscriber-websocket-tls", "", "") c.credentials("test-subscriber-websocket-tls", "", "")
.brokers("iot.fcluster.mireo.hr/mqtt", 8884) .brokers("emqtt.mireo.local/mqtt", 8884)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();

View File

@ -216,7 +216,7 @@ struct varint_parser : x3::parser<varint_parser> {
template <typename It, typename Ctx, typename RCtx, typename Attr> template <typename It, typename Ctx, typename RCtx, typename Attr>
bool parse( bool parse(
It& first, const It last, It& first, const It last,
const Ctx& ctx, RCtx& rctx, Attr& attr const Ctx& ctx, RCtx&, Attr& attr
) const { ) const {
It iter = first; It iter = first;

View File

@ -10,7 +10,9 @@
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/any_completion_handler.hpp> #include <boost/asio/any_completion_handler.hpp>
#include <boost/beast/websocket.hpp> #include <boost/beast/http/field.hpp>
#include <boost/beast/websocket/rfc6455.hpp>
#include <boost/beast/websocket/stream_base.hpp>
#include <async_mqtt5/error.hpp> #include <async_mqtt5/error.hpp>
@ -133,7 +135,7 @@ public:
do_ws_handshake(std::move(ep), std::move(ap)); do_ws_handshake(std::move(ep), std::move(ap));
} }
void do_ws_handshake(endpoint ep, authority_path ap) { void do_ws_handshake(endpoint, authority_path ap) {
if constexpr (has_ws_handshake<Stream>) { if constexpr (has_ws_handshake<Stream>) {
using namespace boost::beast; using namespace boost::beast;

View File

@ -71,7 +71,7 @@ public:
void operator()( void operator()(
on_read, typename Owner::stream_ptr stream_ptr, on_read, typename Owner::stream_ptr stream_ptr,
std::array<std::size_t, 2> ord, error_code read_ec, size_t bytes_read, std::array<std::size_t, 2> ord, error_code read_ec, size_t bytes_read,
error_code timer_ec error_code
) { ) {
if (!_owner.is_open()) if (!_owner.is_open())
return complete(asio::error::operation_aborted, bytes_read); return complete(asio::error::operation_aborted, bytes_read);

View File

@ -11,6 +11,7 @@
#include <boost/asio/recycling_allocator.hpp> #include <boost/asio/recycling_allocator.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/type_traits/remove_cv_ref.hpp>
namespace async_mqtt5::test { namespace async_mqtt5::test {
@ -88,7 +89,7 @@ decltype(auto) async_delay(
delayed_op<BoundArgs...>&& op, delayed_op<BoundArgs...>&& op,
CompletionToken&& token CompletionToken&& token
) { ) {
using Signature = void (error_code, std::remove_cvref_t<BoundArgs>...); using Signature = void (error_code, boost::remove_cv_ref_t<BoundArgs>...);
auto initiation = []( auto initiation = [](
auto handler, asio::cancellation_slot cancel_slot, auto handler, asio::cancellation_slot cancel_slot,

View File

@ -7,6 +7,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/type_traits/remove_cv_ref.hpp>
#include "test_common/delayed_op.hpp" #include "test_common/delayed_op.hpp"
namespace async_mqtt5::test { namespace async_mqtt5::test {
@ -49,7 +51,6 @@ public:
} }
}; };
} // end namespace detail } // end namespace detail
@ -81,15 +82,7 @@ public:
template <typename ...Args> template <typename ...Args>
client_message& reply_with(Args&& ...args) { client_message& reply_with(Args&& ...args) {
// just to allow duration to be the last parameter // just to allow duration to be the last parameter
auto t = std::make_tuple(std::forward<Args>(args)...); return reply_with_dur(std::make_tuple(std::forward<Args>(args)...));
using Tuple = decltype(t);
return[&]<auto... I>(std::index_sequence<I...>) -> client_message& {
return reply_with_impl(
std::get<std::tuple_size_v<Tuple> -1>(t),
std::get<I>(t)...
);
}(std::make_index_sequence<std::tuple_size_v<Tuple> -1>{});
} }
template <typename ...Args> template <typename ...Args>
@ -116,8 +109,25 @@ public:
private: private:
template <typename ...Args> template<typename Tuple, size_t ...I>
requires (std::is_same_v<std::remove_cvref_t<Args>, std::string> && ...) client_message& reply_with_dur(const Tuple& t) {
constexpr auto indices = std::make_index_sequence<
std::tuple_size_v<Tuple> - 1
> {};
return reply_with_impl(
std::get<std::tuple_size_v<Tuple> - 1>(t),
std::get<I>(t)...
);
}
template <
typename ...Args,
std::enable_if_t<
(std::is_same_v<boost::remove_cv_ref_t<Args>, std::string> && ...),
bool
> = true
>
client_message& reply_with_impl(duration af, Args&& ...args) { client_message& reply_with_impl(duration af, Args&& ...args) {
_replies.emplace_back( _replies.emplace_back(
error_code {}, af, std::forward<Args>(args)... error_code {}, af, std::forward<Args>(args)...
@ -164,8 +174,13 @@ class msg_exchange {
std::vector<broker_message> _from_broker; std::vector<broker_message> _from_broker;
public: public:
template <typename ...Args> template <
requires (std::is_same_v<std::remove_cvref_t<Args>, std::string> && ...) typename ...Args,
std::enable_if_t<
(std::is_same_v<boost::remove_cv_ref_t<Args>, std::string> && ...),
bool
> = true
>
client_message& expect(Args&& ...args) { client_message& expect(Args&& ...args) {
_to_broker.emplace_back(this, std::forward<Args>(args)...); _to_broker.emplace_back(this, std::forward<Args>(args)...);
return _to_broker.back(); return _to_broker.back();
@ -174,15 +189,7 @@ public:
template <typename ...Args> template <typename ...Args>
broker_message& send(Args&& ...args) { broker_message& send(Args&& ...args) {
// just to allow duration to be the last parameter // just to allow duration to be the last parameter
auto t = std::make_tuple(std::forward<Args>(args)...); return send_with_dur(std::make_tuple(std::forward<Args>(args)...));
using Tuple = decltype(t);
return[&]<auto... I>(std::index_sequence<I...>) -> broker_message& {
return send_impl(
std::get<std::tuple_size_v<Tuple> -1>(t),
std::get<I>(t)...
);
}(std::make_index_sequence<std::tuple_size_v<Tuple> -1>{});
} }
std::optional<client_message> pop_reply_action() { std::optional<client_message> pop_reply_action() {
@ -207,8 +214,25 @@ public:
private: private:
template <typename ...Args> template<typename Tuple, size_t ...I>
requires (std::is_same_v<std::remove_cvref_t<Args>, std::string> && ...) broker_message& send_with_dur(const Tuple& t) {
constexpr auto indices = std::make_index_sequence<
std::tuple_size_v<Tuple> - 1
> {};
return send_impl(
std::get<std::tuple_size_v<Tuple> - 1>(t),
std::get<I>(t)...
);
}
template <
typename ...Args,
std::enable_if_t<
(std::is_same_v<boost::remove_cv_ref_t<Args>, std::string> && ...),
bool
> = true
>
broker_message& send_impl(duration after, Args&& ...args) { broker_message& send_impl(duration after, Args&& ...args) {
_from_broker.emplace_back( _from_broker.emplace_back(
this, error_code {}, after, std::forward<Args>(args)... this, error_code {}, after, std::forward<Args>(args)...

View File

@ -288,7 +288,7 @@ public:
asio::post(get_executor(), asio::prepend(std::move(handler), ec)); asio::post(get_executor(), asio::prepend(std::move(handler), ec));
}; };
return async_initiate<ConnectToken, void (error_code)>( return asio::async_initiate<ConnectToken, void (error_code)>(
std::move(initiation), token, ep std::move(initiation), token, ep
); );
} }

View File

@ -8,11 +8,68 @@
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast/websocket.hpp> #include <boost/beast/websocket.hpp>
#include <async_mqtt5.hpp> #include <async_mqtt5.hpp>
namespace boost::beast::websocket {
template <typename TeardownHandler>
void async_teardown(
boost::beast::role_type role,
asio::ssl::stream<asio::ip::tcp::socket>& stream,
TeardownHandler&& handler
) {
return stream.async_shutdown(std::forward<TeardownHandler>(handler));
}
} // end namespace boost::beast::websocket
constexpr char mireo_ca[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIDUTCCAjmgAwIBAgIUAzV59EhZA5MXluHNqRi9cBP0x9swDQYJKoZIhvcNAQEL\n"
"BQAwGDEWMBQGA1UEAwwNTWlyZW8gUm9vdCBDQTAeFw0yMjA0MDcxMzM1MjlaFw0z\n"
"MjA0MDQxMzM1MjlaMBgxFjAUBgNVBAMMDU1pcmVvIFJvb3QgQ0EwggEiMA0GCSqG\n"
"SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCin/qsHpdxT3iW0SEHhAcTfESyQcfwGtJE\n"
"jcRrGEj36X6eahyY4AF+4Mlz2vWFeW52ayGXpQKn/z4tChdN80txdY77YmEX7XE0\n"
"HHZYY6toNq/+mNX9h2HvB0GW+8+E0YfNN/HloTxDo3RT8+IovY9OSXt44vY4YtQK\n"
"JbvZIm2Q8Iuv3vfNR05uFa4HcNqFhELh10jss0xG/54Y2NvB6xdKOZ8LRQuIX+Fu\n"
"QRzMiqRFQPUJzWxbKF5I/MFiKWmAG0QNPDnlb8XtPmFTFCWY9X96wOpQOczrxT2+\n"
"+vnTxPA3aTAkz7M4yUuocZQqTlbdfdGOSAENXavewdMCyy5bQsSLAgMBAAGjgZIw\n"
"gY8wHQYDVR0OBBYEFLdUGYfJRf9mbM/fTav9U2vFI+TRMFMGA1UdIwRMMEqAFLdU\n"
"GYfJRf9mbM/fTav9U2vFI+TRoRykGjAYMRYwFAYDVQQDDA1NaXJlbyBSb290IENB\n"
"ghQDNXn0SFkDkxeW4c2pGL1wE/TH2zAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB\n"
"BjANBgkqhkiG9w0BAQsFAAOCAQEAHm5d4YUP8BYcks10UCdswLtxbMUN99fNbnYo\n"
"RMxx4EapwhEZFSNbIZvf1INJd5Po+hH5jteBeFVP+4zKqrhg3I8pjdC4josHmrhS\n"
"28OjOFWp6xNJC43BHnLpc84bH0+XIEBbk7YA6H3GjpsZ7aJkhj/JPjjNq7bmyYN7\n"
"1I9RK4PtIrNtUFbSsHZCZhf8Amtl8PrpktITECjfqCq+8uOAqP4McTIQ1JKwYy6f\n"
"O6iu0eybJCFhWYENTUQyPi1VtEwOpWNLzaXBYdj69Xg8wA/J9RZIoqXWvtHv4rPF\n"
"HGudMEIVB3y2vVLmujvQCqYPZWwbgpy5mN3F4uBNuZhTIwWRFg==\n"
"-----END CERTIFICATE-----\n"
;
namespace async_mqtt5 {
template <typename StreamBase>
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
static constexpr auto client = asio::ssl::stream_base::client;
static constexpr auto server = asio::ssl::stream_base::server;
};
template <typename StreamBase>
void assign_tls_sni(
const authority_path& ap,
asio::ssl::context& ctx,
asio::ssl::stream<StreamBase>& stream
) {
SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str());
}
} // end namespace async_mqtt5
BOOST_AUTO_TEST_SUITE(coroutine/*, *boost::unit_test::disabled()*/) BOOST_AUTO_TEST_SUITE(coroutine/*, *boost::unit_test::disabled()*/)
using namespace async_mqtt5; using namespace async_mqtt5;
@ -81,12 +138,12 @@ BOOST_AUTO_TEST_CASE(tcp_client_check) {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("tcp-tester", "", "") c.credentials("tcp-tester", "", "")
.brokers("mqtt.mireo.local", 1883) .brokers("emqtt.mireo.local", 1883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
asio::steady_timer timer(ioc); asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(10)); timer.expires_after(std::chrono::seconds(5));
timer.async_wait( timer.async_wait(
[&](boost::system::error_code ec) { [&](boost::system::error_code ec) {
@ -107,8 +164,6 @@ BOOST_AUTO_TEST_CASE(tcp_client_check) {
ioc.run(); ioc.run();
} }
// TODO: SSL
BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) { BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
asio::io_context ioc; asio::io_context ioc;
@ -120,12 +175,95 @@ BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
client_type c(ioc, ""); client_type c(ioc, "");
c.credentials("websocket-tcp-tester", "", "") c.credentials("websocket-tcp-tester", "", "")
.brokers("fcluster-5/mqtt", 8083) .brokers("emqtt.mireo.local/mqtt", 8083)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once }) .will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run(); .run();
asio::steady_timer timer(ioc); asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(10)); timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
BOOST_CHECK_MESSAGE(ec, "Failed to receive all the expected replies!");
c.cancel();
ioc.stop();
}
);
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
co_await sanity_check(c);
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_CASE(openssl_tls_client_check) {
asio::io_context ioc;
using stream_type = asio::ssl::stream<asio::ip::tcp::socket>;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
error_code ec;
tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context));
c.credentials("openssl-tls-tester", "", "")
.brokers("emqtt.mireo.local", 8883)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run();
asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
BOOST_CHECK_MESSAGE(ec, "Failed to receive all the expected replies!");
c.cancel();
ioc.stop();
}
);
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
co_await sanity_check(c);
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_CASE(websocket_tls_client_check) {
asio::io_context ioc;
using stream_type = boost::beast::websocket::stream<
asio::ssl::stream<asio::ip::tcp::socket>
>;
error_code ec;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
tls_context.add_certificate_authority(asio::buffer(mireo_ca), ec);
tls_context.set_verify_mode(asio::ssl::verify_peer);
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, "", std::move(tls_context));
c.credentials("websocket-tls-tester", "", "")
.brokers("emqtt.mireo.local/mqtt", 8884)
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
.run();
asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(5));
timer.async_wait( timer.async_wait(
[&](boost::system::error_code ec) { [&](boost::system::error_code ec) {
@ -148,5 +286,4 @@ BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
#endif #endif