diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 8d1eae4d..c3b4dab8 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -25,6 +25,7 @@ FIND_PACKAGE (Boost 1.74.0 REQUIRED COMPONENTS program_options) IF (MQTT_USE_TLS) LIST (APPEND exec_PROGRAMS tls_client.cpp + tls_client_with_sni.cpp tls_server.cpp tls_both.cpp tls_both_client_cert.cpp diff --git a/example/tls_client_with_sni.cpp b/example/tls_client_with_sni.cpp new file mode 100644 index 00000000..7d2a5a3f --- /dev/null +++ b/example/tls_client_with_sni.cpp @@ -0,0 +1,154 @@ +// Copyright Takatoshi Kondo 2015 +// +// 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) + +#include +#include +#include + +#include + +int main(int argc, char** argv) { + if (argc != 4) { + std::cout << argv[0] << " host port cacert_file" << std::endl; + return -1; + } + + MQTT_NS::setup_log(); + + boost::asio::io_context ioc; + + std::string host = argv[1]; + auto port = argv[2]; + std::string cacert = argv[3]; + + std::uint16_t pid_sub1; + std::uint16_t pid_sub2; + + int count = 0; + + // Create TLS client + auto c = MQTT_NS::make_tls_sync_client(ioc, host, port); + using packet_id_t = typename std::remove_reference_t::packet_id_t; + + auto connect = + [&] { + // create custom socket + auto stream = + std::make_shared< + MQTT_NS::tcp_endpoint< + MQTT_NS::tls::stream, + MQTT_NS::strand + > + >(ioc, c->get_ssl_context()); + + if (!SSL_set_tlsext_host_name(MQTT_NS::any_cast(stream->native_handle()), host.c_str())) { + std::cout << "SSL_set_tlsext_host_name return false" << std::endl; + return false; + } + c->connect(MQTT_NS::force_move(stream)); + return true; + }; + + auto disconnect = [&] { + if (++count == 5) c->disconnect(); + }; + + // Setup client + c->set_client_id("cid1"); + c->set_clean_session(true); + c->get_ssl_context().load_verify_file(cacert); + + // Setup handlers + c->set_connack_handler( + [&c, &pid_sub1, &pid_sub2] + (bool sp, MQTT_NS::connect_return_code connack_return_code){ + std::cout << "Connack handler called" << std::endl; + std::cout << "Session Present: " << std::boolalpha << sp << std::endl; + std::cout << "Connack Return Code: " + << MQTT_NS::connect_return_code_to_str(connack_return_code) << std::endl; + if (connack_return_code == MQTT_NS::connect_return_code::accepted) { + pid_sub1 = c->subscribe("mqtt_client_cpp/topic1", MQTT_NS::qos::at_most_once); + pid_sub2 = c->subscribe( + std::vector> + { + { "mqtt_client_cpp/topic2_1", MQTT_NS::subscribe_options(MQTT_NS::qos::at_least_once) }, + { "mqtt_client_cpp/topic2_2", MQTT_NS::subscribe_options(MQTT_NS::qos::exactly_once) } + } + ); + } + return true; + }); + c->set_close_handler( + [] + (){ + std::cout << "closed." << std::endl; + }); + c->set_error_handler( + [] + (MQTT_NS::error_code ec){ + std::cout << "error: " << ec.message() << std::endl; + }); + c->set_puback_handler( + [&] + (packet_id_t packet_id){ + std::cout << "puback received. packet_id: " << packet_id << std::endl; + disconnect(); + return true; + }); + c->set_pubrec_handler( + [&] + (packet_id_t packet_id){ + std::cout << "pubrec received. packet_id: " << packet_id << std::endl; + return true; + }); + c->set_pubcomp_handler( + [&] + (packet_id_t packet_id){ + std::cout << "pubcomp received. packet_id: " << packet_id << std::endl; + disconnect(); + return true; + }); + c->set_suback_handler( + [&] + (packet_id_t packet_id, std::vector results){ + std::cout << "suback received. packet_id: " << packet_id << std::endl; + for (auto const& e : results) { + std::cout << "[client] subscribe result: " << e << std::endl; + } + if (packet_id == pid_sub1) { + c->publish("mqtt_client_cpp/topic1", "test1", MQTT_NS::qos::at_most_once); + } + else if (packet_id == pid_sub2) { + c->publish("mqtt_client_cpp/topic2_1", "test2_1", MQTT_NS::qos::at_least_once); + c->publish("mqtt_client_cpp/topic2_2", "test2_2", MQTT_NS::qos::exactly_once); + } + return true; + }); + c->set_publish_handler( + [&] + (MQTT_NS::optional packet_id, + MQTT_NS::publish_options pubopts, + MQTT_NS::buffer topic_name, + MQTT_NS::buffer contents){ + std::cout << "publish received." + << " dup: " << pubopts.get_dup() + << " qos: " << pubopts.get_qos() + << " retain: " << pubopts.get_retain() << std::endl; + if (packet_id) + std::cout << "packet_id: " << *packet_id << std::endl; + std::cout << "topic_name: " << topic_name << std::endl; + std::cout << "contents: " << contents << std::endl; + disconnect(); + return true; + }); + + // Connect + if (!connect()) { + std::cout << "connect failed" << std::endl; + } + + ioc.run(); +}