From 688823d28da0cf5652e6684a9d4bfbc55c2fa30e Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 22 Feb 2023 16:45:49 +0900 Subject: [PATCH] Remove libmosquitto dependency libmosquitto may not installed some targets. Use dlopen / dlsym instead. Change-Id: I5cc4db1eb1f8ea7eab069e7d5e52143e53ce33de Signed-off-by: Sangyoon Jang --- CMakeLists.txt | 1 - packaging/cion.spec | 1 - plugin/cion-mqtt-plugin/CMakeLists.txt | 1 - plugin/cion-mqtt-plugin/mqtt/mqtt_service.cc | 152 ++++++++++++++++--- plugin/cion-mqtt-plugin/mqtt/mqtt_service.hh | 92 ++++++++++- 5 files changed, 220 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64a58c1..9b642b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,6 @@ PKG_CHECK_MODULES(CYNARA_DEPS REQUIRED cynara-client cynara-session) PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog) PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0) PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) -PKG_CHECK_MODULES(LIBMOSQUITTO_DEPS REQUIRED libmosquitto) PKG_CHECK_MODULES(PARCEL_DEPS REQUIRED parcel) PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info) PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue) diff --git a/packaging/cion.spec b/packaging/cion.spec index 5889511..4135cdd 100644 --- a/packaging/cion.spec +++ b/packaging/cion.spec @@ -22,7 +22,6 @@ BuildRequires: pkgconfig(cynara-session) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gmock) -BuildRequires: pkgconfig(libmosquitto) BuildRequires: pkgconfig(parcel) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(tizen-shared-queue) diff --git a/plugin/cion-mqtt-plugin/CMakeLists.txt b/plugin/cion-mqtt-plugin/CMakeLists.txt index 48a01a5..ec40a64 100644 --- a/plugin/cion-mqtt-plugin/CMakeLists.txt +++ b/plugin/cion-mqtt-plugin/CMakeLists.txt @@ -27,7 +27,6 @@ APPLY_PKG_CONFIG(${TARGET_MQTT_PLUGIN} PUBLIC CYNARA_DEPS DLOG_DEPS GLIB_DEPS - LIBMOSQUITTO_DEPS PARCEL_DEPS PKGMGR_INFO_DEPS TIZEN_SHARED_QUEUE_DEPS diff --git a/plugin/cion-mqtt-plugin/mqtt/mqtt_service.cc b/plugin/cion-mqtt-plugin/mqtt/mqtt_service.cc index d5d7ca5..ec533d3 100755 --- a/plugin/cion-mqtt-plugin/mqtt/mqtt_service.cc +++ b/plugin/cion-mqtt-plugin/mqtt/mqtt_service.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -39,28 +38,136 @@ namespace { -#define DIRECT_ACCESS_FUNC "_request_handler_direct_access" +constexpr char kMosquittoLibPath[] = LIB_PATH"/libmosquitto.so.1"; } // namespace namespace GenMQTT { +MqttService::MqttLibraryAdapter::MqttLibraryAdapter() + : new_(nullptr), destroy_(nullptr), connect_callback_set_(nullptr), + disconnect_callback_set_(nullptr), message_callback_set_(nullptr), + username_pw_set_(nullptr), loop_start_(nullptr), connect_(nullptr), + disconnect_(nullptr), subscribe_(nullptr), unsubscribe_(nullptr), + publish_(nullptr) { + handle_ = dlopen(kMosquittoLibPath, RTLD_GLOBAL | RTLD_LAZY | RTLD_NODELETE); + if (handle_ == nullptr) { + LOG(ERROR) << "Failed to open library: " << kMosquittoLibPath << ", : " + << dlerror(); + THROW(error::MQTT_PLUGIN_ERROR_OPERATION_FAILED); + } + + if (!LoadSymbols()) { + dlclose(handle_); + THROW(error::MQTT_PLUGIN_ERROR_OPERATION_FAILED); + } +} + +MqttService::MqttLibraryAdapter::~MqttLibraryAdapter() { + dlclose(handle_); +} + +bool MqttService::MqttLibraryAdapter::LoadSymbols() { + new_ = reinterpret_cast(dlsym(handle_, "mosquitto_new")); + if (!new_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + destroy_ = reinterpret_cast(dlsym(handle_, "mosquitto_destroy")); + if (!destroy_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + connect_callback_set_ = reinterpret_cast( + dlsym(handle_, "mosquitt_connect_callback_set")); + if (!connect_callback_set_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + disconnect_callback_set_ = reinterpret_cast( + dlsym(handle_, "mosquitt_disconnnect_callback_set")); + if (!disconnect_callback_set_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + message_callback_set_ = reinterpret_cast( + dlsym(handle_, "mosquitt_message_callback_set")); + if (!message_callback_set_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + username_pw_set_ = reinterpret_cast( + dlsym(handle_, "mosquitto_username_pw_set")); + if (!username_pw_set_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + loop_start_ = reinterpret_cast( + dlsym(handle_, "mosquitto_loop_start")); + if (!loop_start_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + connect_ = reinterpret_cast(dlsym(handle_, "mosquitto_connect")); + if (!connect_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + disconnect_ = reinterpret_cast( + dlsym(handle_, "mosquitto_disconnect")); + if (!disconnect_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + subscribe_ = reinterpret_cast( + dlsym(handle_, "mosquitto_subscribe")); + if (!subscribe_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + unsubscribe_ = reinterpret_cast( + dlsym(handle_, "mosquitto_unsubscribe")); + if (!unsubscribe_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + publish_ = reinterpret_cast(dlsym(handle_, "mosquitto_publish")); + if (!publish_) { + LOG(ERROR) << "Failed to load symbol"; + return false; + } + + return true; +} + MqttService::MqttService() { - mosq_ = mosquitto_new(nullptr, true, this); + mqtt_lib_ = std::make_unique(); + mosq_ = mqtt_lib_->mosquitto_new(nullptr, true, this); if (mosq_ == nullptr) THROW(error::MQTT_PLUGIN_ERROR_OUT_OF_MEMORY); // consider using v5? - mosquitto_connect_callback_set(mosq_, - [](mosquitto* mosq, void* obj, int rc) { + mqtt_lib_->mosquitto_connect_callback_set(mosq_, + [](void* mosq, void* obj, int rc) { LOG(ERROR) << "ON CONNECT"; }); - mosquitto_disconnect_callback_set(mosq_, - [](mosquitto* mosq, void* obj, int rc) { + mqtt_lib_->mosquitto_disconnect_callback_set(mosq_, + [](void* mosq, void* obj, int rc) { LOG(ERROR) << "ON DISCONNECT"; }); - mosquitto_message_callback_set(mosq_, - [](mosquitto* mosq, void* obj, const struct mosquitto_message* message){ + mqtt_lib_->mosquitto_message_callback_set(mosq_, + [](void* mosq, void* obj, const struct MqttLibraryAdapter::mosquitto_message* message){ LOG(ERROR) << "ON MESSAGE"; MqttService* service = static_cast(obj); @@ -150,7 +257,7 @@ MqttService::MqttService() { MqttService::~MqttService() { LOG(ERROR) << "~MqttService"; if (mosq_) - mosquitto_destroy(mosq_); + mqtt_lib_->mosquitto_destroy(mosq_); g_main_loop_quit(loop_); thread_.join(); @@ -172,23 +279,24 @@ MqttService::SubscribeData::SubscribeData(mqtt_plugin_sub_fn callback, void MqttService::Connect(const std::string &broker_ip, int broker_port, const std::string &user_name, const std::string &password) { - int ret = mosquitto_username_pw_set(mosq_, user_name.c_str(), + int ret = mqtt_lib_->mosquitto_username_pw_set(mosq_, user_name.c_str(), password.c_str()); - if (ret != MOSQ_ERR_SUCCESS) { + if (ret != 0) { LOG(ERROR) << "Failed to set username and password: " << ret; THROW(ret); } - ret = mosquitto_loop_start(mosq_); - if (ret != MOSQ_ERR_SUCCESS) { + ret = mqtt_lib_->mosquitto_loop_start(mosq_); + if (ret != 0) { LOG(ERROR) << "Failed to start mosquitto loop: " << ret; THROW(ret); } // same as mqtt int keep_alive = 60; - ret = mosquitto_connect(mosq_, broker_ip.c_str(), broker_port, keep_alive); - if (ret != MOSQ_ERR_SUCCESS) { + ret = mqtt_lib_->mosquitto_connect(mosq_, broker_ip.c_str(), broker_port, + keep_alive); + if (ret != 0) { LOG(ERROR) << "Failed to connect broker: " << ret; THROW(ret); } @@ -198,9 +306,9 @@ void MqttService::Publish(const std::string &topic, const unsigned char* data, size_t data_size) { int mid = -1; int qos = 2; - int ret = mosquitto_publish(mosq_, &mid, topic.c_str(), data_size, + int ret = mqtt_lib_->mosquitto_publish(mosq_, &mid, topic.c_str(), data_size, static_cast(data), qos, false); - if (ret != MOSQ_ERR_SUCCESS) { + if (ret != 0) { LOG(ERROR) << "Failed to publish: " << ret; THROW(ret); } @@ -210,8 +318,8 @@ void MqttService::Subscribe(const std::string &topic, mqtt_plugin_sub_fn cb, void *user_data) { int mid = -1; int qos = 2; - int ret = mosquitto_subscribe(mosq_, &mid, topic.c_str(), qos); - if (ret != MOSQ_ERR_SUCCESS) { + int ret = mqtt_lib_->mosquitto_subscribe(mosq_, &mid, topic.c_str(), qos); + if (ret != 0) { LOG(ERROR) << "Failed to subscribe: " << ret; THROW(ret); } @@ -221,7 +329,7 @@ void MqttService::Subscribe(const std::string &topic, mqtt_plugin_sub_fn cb, int MqttService::Unsubscribe(const std::string& topic) { int mid = -1; - return mosquitto_unsubscribe(mosq_, &mid, topic.c_str()); + return mqtt_lib_->mosquitto_unsubscribe(mosq_, &mid, topic.c_str()); } bool MqttService::Disconnect() { @@ -235,7 +343,7 @@ bool MqttService::Disconnect() { peer_watchdog_.reset(); peer_dp_.reset(); - int ret = mosquitto_disconnect(mosq_); + int ret = mqtt_lib_->mosquitto_disconnect(mosq_); if (ret) { LOG(ERROR) << "Failed to disconnect broker: " << ret; return false; diff --git a/plugin/cion-mqtt-plugin/mqtt/mqtt_service.hh b/plugin/cion-mqtt-plugin/mqtt/mqtt_service.hh index 8df539b..bf56e4a 100755 --- a/plugin/cion-mqtt-plugin/mqtt/mqtt_service.hh +++ b/plugin/cion-mqtt-plugin/mqtt/mqtt_service.hh @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -61,12 +60,101 @@ class MqttService { int Unsubscribe(const std::string& topic); private: + class MqttLibraryAdapter { + public: + struct mosquitto_message { + int mid; + char* topic; + void* payload; + int payloadlen; + int qos; + bool retain; + }; + using new_fn = void*(*)(const char*, bool, void*); + using destroy_fn = void(*)(void*); + using connnect_callback_fn = void(*)(void*, void*, int); + using connect_callback_set_fn = void(*)(void*, connnect_callback_fn); + using disconnect_callback_set_fn = void(*)(void*, connnect_callback_fn); + using message_callback_fn = void(*)(void*, void*, + const struct mosquitto_message*); + using message_callback_set_fn = void(*)(void*, message_callback_fn); + using username_pw_set_fn = int(*)(void*, const char*, const char*); + using loop_start_fn = int(*)(void*); + using connect_fn = int(*)(void*, const char*, int ,int); + using disconnect_fn = int(*)(void*); + using subscribe_fn = int(*)(void*, int*, const char*, int qos); + using unsubscribe_fn = int(*)(void*, int*, const char*); + using publish_fn = int(*)(void*, int*, const char*, int, const void*, int, + bool); + + MqttLibraryAdapter(); + ~MqttLibraryAdapter(); + void* mosquitto_new(const char* id, bool clean_session, void* obj) { + return new_(id, clean_session, obj); + } + void mosquitto_destroy(void* mosq) { + destroy_(mosq); + } + void mosquitto_connect_callback_set(void* mosq, connnect_callback_fn cb) { + connect_callback_set_(mosq, cb); + } + void mosquitto_disconnect_callback_set(void* mosq, + connnect_callback_fn cb) { + disconnect_callback_set_(mosq, cb); + } + void mosquitto_message_callback_set(void* mosq, message_callback_fn cb) { + message_callback_set_(mosq, cb); + } + int mosquitto_username_pw_set(void* mosq, const char* username, + const char* password) { + return username_pw_set_(mosq, username, password); + } + int mosquitto_loop_start(void* mosq) { + return loop_start_(mosq); + } + int mosquitto_connect(void* mosq, const char* host, int port, + int keepalive) { + return connect_(mosq, host, port, keepalive); + } + int mosquitto_disconnect(void* mosq) { + return disconnect_(mosq); + } + int mosquitto_subscribe(void* mosq, int* mid, const char* sub, int qos) { + return subscribe_(mosq, mid, sub, qos); + } + int mosquitto_unsubscribe(void* mosq, int* mid, const char* sub) { + return unsubscribe_(mosq, mid, sub); + } + int mosquitto_publish(void* mosq, int* mid, const char* topic, + int payloadlen, const void* payload, int qos, bool retain) { + return publish_(mosq, mid, topic, payloadlen, payload, qos, retain); + } + + private: + bool LoadSymbols(); + + void* handle_; + new_fn new_; + destroy_fn destroy_; + connect_callback_set_fn connect_callback_set_; + disconnect_callback_set_fn disconnect_callback_set_; + message_callback_set_fn message_callback_set_; + username_pw_set_fn username_pw_set_; + loop_start_fn loop_start_; + connect_fn connect_; + disconnect_fn disconnect_; + subscribe_fn subscribe_; + unsubscribe_fn unsubscribe_; + publish_fn publish_; + }; + struct SubscribeData { SubscribeData(mqtt_plugin_sub_fn cb, void* user_data); mqtt_plugin_sub_fn cb; void* user_data; }; - struct mosquitto* mosq_; + std::unique_ptr mqtt_lib_; + void* mosq_; std::string iface_name_; std::thread thread_; -- 2.34.1