// // 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) // //[hello_world_over_websocket_tls #include #include #include #include #include #include #include namespace boost::beast::websocket { // boost::beast::websocket::async_teardown is a free function designed to initiate the asynchronous teardown of a connection. // The specific behaviour of this function is based on the NextLayer type (Socket type) used to create the ``__WEBSOCKET_STREAM__``. // ``__Beast__`` library includes an implementation of this function for ``__TCP_SOCKET__``. // However, the callers are responsible for providing a suitable overload of this function for any other type, // such as ``__SSL_STREAM__`` as shown in this example. // See ``__BEAST_ASYNC_TEARDOWN__`` for more information. template void async_teardown( boost::beast::role_type role, asio::ssl::stream& stream, TeardownHandler&& handler ) { return stream.async_shutdown(std::forward(handler)); } } // end namespace boost::beast::websocket // External customization point. namespace async_mqtt5 { template struct tls_handshake_type> { static constexpr auto client = boost::asio::ssl::stream_base::client; static constexpr auto server = boost::asio::ssl::stream_base::server; }; // This client uses this function to indicate which hostname it is // attempting to connect to at the start of the handshaking process. template void assign_tls_sni( const authority_path& ap, boost::asio::ssl::context& ctx, boost::asio::ssl::stream& stream ) { SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str()); } } // end namespace async_mqtt5 // The certificate file in the PEM format. constexpr char ca_cert[] = "-----BEGIN CERTIFICATE-----\n" "...........................\n" "-----END CERTIFICATE-----\n" ; int main() { boost::asio::io_context ioc; // Context satisfying ``__TlsContext__`` requirements that the underlying SSL stream will use. // The purpose of the context is to allow us to set up TLS/SSL-related options. // See ``__SSL__`` for more information and options. boost::asio::ssl::context context(boost::asio::ssl::context::tls_client); async_mqtt5::error_code ec; // Add the trusted certificate authority for performing verification. context.add_certificate_authority(boost::asio::buffer(ca_cert), ec); if (ec) std::cout << "Failed to add certificate authority!" << std::endl; ec.clear(); // Set peer verification mode used by the context. // This will verify that the server's certificate is valid and signed by a trusted certificate authority. context.set_verify_mode(boost::asio::ssl::verify_peer, ec); if (ec) std::cout << "Failed to set peer verification mode!" << std::endl; ec.clear(); // Construct the Client with WebSocket/SSL as the underlying stream // with ``__SSL_CONTEXT__`` as the ``__TlsContext__`` type. async_mqtt5::mqtt_client< boost::beast::websocket::stream>, boost::asio::ssl::context > client(ioc, std::move(context)); // 8884 is the default Websocket/TLS MQTT port. client.brokers("", 8884) .async_run(boost::asio::detached); client.async_publish( "", "Hello world!", async_mqtt5::retain_e::no, async_mqtt5::publish_props{}, [&client](async_mqtt5::error_code ec) { std::cout << ec.message() << std::endl; client.async_disconnect(boost::asio::detached); } ); ioc.run(); } //]