diff --git a/README.md b/README.md index 399bc8f..1607b92 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Getting Started --------- Async.MQTT5 is a header-only library. To use Async.MQTT5 it requires the following: - **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. - **OpenSSL**. 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). Async.MQTT5 has been tested with the following compilers: diff --git a/doc/qbk/01_intro.qbk b/doc/qbk/01_intro.qbk index fd59442..9a5a25d 100644 --- a/doc/qbk/01_intro.qbk +++ b/doc/qbk/01_intro.qbk @@ -154,7 +154,7 @@ __Self__ is a header-only library. To use __Self__ it requires the following: * [*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. * [*OpenSSL]. If you require an SSL connection by using [asioreflink ssl__stream ssl::stream]. __Self__ has been tested with the following compilers: diff --git a/example/hello_world_over_websocket_tcp.cpp b/example/hello_world_over_websocket_tcp.cpp index ed5d069..221a1bf 100644 --- a/example/hello_world_over_websocket_tcp.cpp +++ b/example/hello_world_over_websocket_tcp.cpp @@ -15,6 +15,7 @@ #include #include +#include // WebSocket traits int main() { boost::asio::io_context ioc; diff --git a/example/hello_world_over_websocket_tls.cpp b/example/hello_world_over_websocket_tls.cpp index 65a7f75..d7e858a 100644 --- a/example/hello_world_over_websocket_tls.cpp +++ b/example/hello_world_over_websocket_tls.cpp @@ -17,6 +17,7 @@ #include // async_teardown specialization for websocket ssl stream #include +#include // WebSocket traits // External customization point. namespace async_mqtt5 { diff --git a/include/async_mqtt5/detail/async_traits.hpp b/include/async_mqtt5/detail/async_traits.hpp index 781ed64..ede57a9 100644 --- a/include/async_mqtt5/detail/async_traits.hpp +++ b/include/async_mqtt5/detail/async_traits.hpp @@ -25,12 +25,19 @@ namespace async_mqtt5 { namespace asio = boost::asio; +// TLS + template struct tls_handshake_type {}; template void assign_tls_sni(const authority_path& ap, TlsContext& ctx, TlsStream& s); +// WebSocket + +template +struct ws_handshake_traits {}; + namespace detail { // tracking executor diff --git a/include/async_mqtt5/impl/connect_op.hpp b/include/async_mqtt5/impl/connect_op.hpp index 28d620b..1710568 100644 --- a/include/async_mqtt5/impl/connect_op.hpp +++ b/include/async_mqtt5/impl/connect_op.hpp @@ -27,10 +27,6 @@ #include #include -#include -#include -#include - #include #include @@ -171,35 +167,15 @@ public: } void do_ws_handshake(endpoint ep, authority_path ap) { - if constexpr (has_ws_handshake) { - using namespace boost::beast; - - // We'll need to turn off read timeouts on the underlying stream - // because the websocket stream has its own timeout system. - - // Set suggested timeout settings for the websocket - _stream.set_option( - websocket::stream_base::timeout::suggested(role_type::client) - ); - - _stream.binary(true); - - // Set a decorator to change the User-Agent of the handshake - _stream.set_option(websocket::stream_base::decorator( - [](websocket::request_type& req) { - req.set(http::field::sec_websocket_protocol, "mqtt"); - req.set(http::field::user_agent, "boost.mqtt"); - }) - ); - - _stream.async_handshake( - ap.host + ':' + ap.port, ap.path, + if constexpr (has_ws_handshake) + // If you get a compilation error here, + // it might be because of a missing include + ws_handshake_traits::async_handshake( + _stream, std::move(ap), asio::append( - asio::prepend(std::move(*this), on_ws_handshake {}), - ep + asio::prepend(std::move(*this), on_ws_handshake {}), ep ) ); - } else (*this)(on_ws_handshake {}, error_code {}, ep); } diff --git a/include/async_mqtt5/websocket.hpp b/include/async_mqtt5/websocket.hpp new file mode 100644 index 0000000..9fe68d0 --- /dev/null +++ b/include/async_mqtt5/websocket.hpp @@ -0,0 +1,54 @@ +// +// 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) +// + +#ifndef ASYNC_MQTT5_WEBSOCKET_HPP +#define ASYNC_MQTT5_WEBSOCKET_HPP + +#include +#include +#include + +#include + +namespace async_mqtt5 { + +// Trait definition for Beast +template +struct ws_handshake_traits> { + + template + static decltype(auto) async_handshake( + boost::beast::websocket::stream& stream, + authority_path ap, CompletionToken&& token + ) { + using namespace boost::beast; + + // Set suggested timeout settings for the websocket + stream.set_option( + websocket::stream_base::timeout::suggested(role_type::client) + ); + + stream.binary(true); + + // Set a decorator to change the User-Agent of the handshake + stream.set_option(websocket::stream_base::decorator( + [](websocket::request_type& req) { + req.set(http::field::sec_websocket_protocol, "mqtt"); + req.set(http::field::user_agent, "boost.mqtt"); + }) + ); + + stream.async_handshake( + ap.host + ':' + ap.port, ap.path, + std::forward(token) + ); + } +}; + +} // end namespace async_mqtt5 + +#endif // !ASYNC_MQTT5_WEBSOCKET_HPP diff --git a/test/integration/client.cpp b/test/integration/client.cpp index c48c406..e1f0239 100644 --- a/test/integration/client.cpp +++ b/test/integration/client.cpp @@ -25,6 +25,7 @@ #include #include +#include namespace async_mqtt5 { diff --git a/test/integration/mqtt_features.cpp b/test/integration/mqtt_features.cpp index 4e111a9..0d67ce6 100644 --- a/test/integration/mqtt_features.cpp +++ b/test/integration/mqtt_features.cpp @@ -26,6 +26,7 @@ #include #include +#include BOOST_AUTO_TEST_SUITE(mqtt_features/*, *boost::unit_test::disabled()*/) diff --git a/test/unit/default_completion_tokens.cpp b/test/unit/default_completion_tokens.cpp index e955575..3458821 100644 --- a/test/unit/default_completion_tokens.cpp +++ b/test/unit/default_completion_tokens.cpp @@ -23,6 +23,7 @@ #include // async_teardown for asio::ssl::socket #include +#include namespace async_mqtt5 { diff --git a/test/unit/logger.cpp b/test/unit/logger.cpp index 2f063b5..4f548a0 100644 --- a/test/unit/logger.cpp +++ b/test/unit/logger.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "test_common/message_exchange.hpp" #include "test_common/test_service.hpp"