From 6da4ca5b0c3eb98fe2ff3757d71dfd4824e99b4f Mon Sep 17 00:00:00 2001 From: Jaemin Ryu Date: Wed, 22 Apr 2020 10:21:46 +0900 Subject: [PATCH] Use dbus for event notification Event motification primitives implemented in the klay does not support a on-demand model. So any events when the service reactivated, will be lost. Change-Id: Ifc0c68052f3bc8997fb016ada1185753d3fb6379 --- lib/client.cpp | 42 +++++++++++++++++++++---------- lib/client.h | 19 ++------------ lib/ode/internal-encryption.cpp | 2 +- lib/ode/luks.cpp | 19 +------------- server/CMakeLists.txt | 1 + server/event.cpp | 56 +++++++++++++++++++++++++++++++++++++++++ server/event.h | 29 +++++++++++++++++++++ server/internal-encryption.cpp | 6 ++--- server/server.cpp | 33 ++---------------------- server/server.h | 5 ++-- 10 files changed, 125 insertions(+), 87 deletions(-) create mode 100644 server/event.cpp create mode 100644 server/event.h diff --git a/lib/client.cpp b/lib/client.cpp index 435f293..7c8c286 100644 --- a/lib/client.cpp +++ b/lib/client.cpp @@ -13,16 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License */ - +#include #include "client.h" +const std::string SIGNAL_OBJECT_PATH = "/org/tizen/OnDeviceEncryption"; +const std::string SIGNAL_EVENT_INTERFACE = "org.tizen.OnDeviceEncryption.Event"; + ClientContext::ClientContext() noexcept { + mainloop.reset(new ScopedGMainLoop); } ClientContext::~ClientContext() noexcept { disconnect(); + mainloop.reset(); } int ClientContext::connect(const std::string& address) noexcept @@ -48,26 +53,37 @@ void ClientContext::disconnect() noexcept } int ClientContext::subscribeSignal(const std::string& name, - const SignalListener& listener, + const SignalListener& handler, void* data) { - auto listenerDispatcher = [listener, data](std::string name) { - listener(data); - }; - + int ret = -1; try { - int ret = client->subscribe - (SUBSCRIBER_REGISTER, name, listenerDispatcher); - if (ret < 0) - return ode::error::Unknown; + mainloop->dispatch([&]() { + auto task = [name, handler, data](dbus::Variant variant) { + char *state = NULL; + variant.get("(s)", &state); + std::cout << "Signal: " << state << std::endl; + handler(data); + }; + + dbus::signal::Receiver receiver(SIGNAL_OBJECT_PATH, SIGNAL_EVENT_INTERFACE); + ret = receiver.subscribe(name, std::move(task)); + }); return ret; } catch (runtime::Exception& e) { - std::cout << e.what() << std::endl; + std::cerr << e.what() << std::endl; return ode::error::Unknown; } } -void ClientContext::unsubscribeSignal(int subscriberId) +void ClientContext::unsubscribeSignal(int id) { - client->unsubscribe(SUBSCRIBER_UNREGISTER, subscriberId); + try { + mainloop->dispatch([&]() { + dbus::signal::Receiver receiver(SIGNAL_OBJECT_PATH, SIGNAL_EVENT_INTERFACE); + receiver.unsubscribe(id); + }); + } catch (runtime::Exception& e) { + std::cerr << e.what() << std::endl; + } } diff --git a/lib/client.h b/lib/client.h index 691e96e..a07255d 100644 --- a/lib/client.h +++ b/lib/client.h @@ -23,15 +23,13 @@ #include #include +#include typedef std::function SignalListener; typedef std::unique_ptr RmiClientPtr; class ClientContext final { - const char* SUBSCRIBER_REGISTER = "ServerContext::registerNotificationSubscriber"; - const char* SUBSCRIBER_UNREGISTER = "ServerContext::unregisterNotificationSubscriber"; - public: ClientContext() noexcept; ~ClientContext() noexcept; @@ -47,20 +45,6 @@ public: int subscribeSignal(const std::string& name, const SignalListener& listener, void* data); void unsubscribeSignal(int subscriberId); - template - int subscribeSignal(const std::string& name, const std::function& listener) - { - try { - int ret = client->subscribe(SUBSCRIBER_REGISTER, name, listener); - if (ret < 0) - return ode::error::Unknown; - return ret; - } catch (runtime::Exception& e) { - std::cout << e.what() << std::endl; - return ode::error::Unknown; - } - } - template Interface createInterface(Args&&... args) noexcept { @@ -69,6 +53,7 @@ public: private: RmiClientPtr client; + std::unique_ptr mainloop; }; #endif //__ODE_CLIENT_H__ diff --git a/lib/ode/internal-encryption.cpp b/lib/ode/internal-encryption.cpp index de808c0..a69e265 100644 --- a/lib/ode/internal-encryption.cpp +++ b/lib/ode/internal-encryption.cpp @@ -239,7 +239,7 @@ int ode_internal_encryption_set_mount_event_cb(ode_mount_event_cb callback, void mountEventCallbackContext.reset(new ClientContext); RET_ON_FAILURE(mountEventCallbackContext->connect() == 0, ODE_ERROR_CONNECTION_REFUSED); - int ret = mountEventCallbackContext->subscribeSignal("InternalEncryptionServer::mount", callback, user_data); + int ret = mountEventCallbackContext->subscribeSignal("internal", callback, user_data); if (ret < 0) return toApiError(ret); diff --git a/lib/ode/luks.cpp b/lib/ode/luks.cpp index d92e50a..b878bff 100644 --- a/lib/ode/luks.cpp +++ b/lib/ode/luks.cpp @@ -26,7 +26,6 @@ using namespace ode; namespace { -std::unique_ptr luksEventCallbackContext; int luks_format_internal(bool sync, const char* device, const char* password) { @@ -86,27 +85,11 @@ int ode_luks_close(const char* mapping) int ode_luks_set_event_cb(ode_luks_event_cb callback, void *user_data) { - int ret; - - RET_ON_FAILURE(callback, ODE_ERROR_INVALID_PARAMETER); - - luksEventCallbackContext.reset(new ClientContext); - RET_ON_FAILURE(luksEventCallbackContext->connect() == 0, ODE_ERROR_CONNECTION_REFUSED); - - std::functioncb = [callback, user_data](std::string, int op, int res) { - callback(static_cast(op), toApiError(res), user_data); - }; - - ret = luksEventCallbackContext->subscribeSignal(Luks::NOTIFICATION, cb); - if (ret < 0) - return toApiError(ret); - - return ODE_ERROR_NONE; + return ODE_ERROR_UNKNOWN; } void ode_luks_unset_event_cb() { - luksEventCallbackContext.reset(); } int ode_luks_format_sync(const char* device, const char* password) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 085003a..6526204 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -14,6 +14,7 @@ # limitations under the License. # SET(SERVER_SRCS main.cpp + event.cpp server.cpp misc.cpp ext4-tool.cpp diff --git a/server/event.cpp b/server/event.cpp new file mode 100644 index 0000000..4e4cb12 --- /dev/null +++ b/server/event.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "event.h" +#include "logger.h" + +#include +#include +#include + +const std::string SIGNAL_OBJECT_PATH = "/org/tizen/OnDeviceEncryption"; +const std::string SIGNAL_EVENT_INTERFACE = "org.tizen.OnDeviceEncryption.Event"; + +const std::string manifest = + "" + " " + " " + " " + " " + " " + ""; + +void EventNotifier::init(void) noexcept +{ + try { + dbus::Connection& conn = dbus::Connection::getSystem(); + conn.registerObject(SIGNAL_OBJECT_PATH, manifest, nullptr, nullptr); + WARN(SINK, "Success to init event-notifier."); + } catch(runtime::Exception& e) { + ERROR(SINK, e.what()); + } +} + +void EventNotifier::emit(const std::string& name, const std::string& state) noexcept +{ + try { + dbus::signal::Sender sender(SIGNAL_OBJECT_PATH, SIGNAL_EVENT_INTERFACE); + sender.emit(name, "(s)", state.c_str()); + WARN(SINK, "Event '" << name << "' has notified with state '" << state << "'"); + } catch(runtime::Exception& e) { + ERROR(SINK, e.what() << ", name: " << name << ", state: " << state); + } +} diff --git a/server/event.h b/server/event.h new file mode 100644 index 0000000..08509bd --- /dev/null +++ b/server/event.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __ODE_EVENT_NOTIFIER_H__ +#define __ODE_EVENT_NOTIFIER_H__ + +#include + +class EventNotifier { +public: + static void init(void) noexcept; + static void create(const std::string& name) noexcept; + static void emit(const std::string& name, const std::string& state) noexcept; +}; + +#endif //__ODE_EVENT_NOTIFIER_H__ diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index 20449e5..a81302a 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -449,8 +449,6 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv, server.expose(this, "", (unsigned int)(InternalEncryptionServer::getSupportedOptions)()); server.expose(this, "", (std::string)(InternalEncryptionServer::getDevicePath)()); - server.createNotification("InternalEncryptionServer::mount"); - std::string source = findDevPath(); if (getStateInternal() == State::Encrypted) { @@ -536,7 +534,7 @@ int InternalEncryptionServer::mount(const std::vector &mk, unsign try { engine->mount(key, getOptions()); - server.notify("InternalEncryptionServer::mount"); + EventNotifier::emit("internal", "mounted"); runtime::File("/tmp/.lazy_mount").create(O_WRONLY); runtime::File("/tmp/.unlock_mnt").create(O_WRONLY); @@ -696,7 +694,7 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int INFO(SINK, "Encryption completed."); ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted"); - server.notify("InternalEncryptionServer::mount"); + EventNotifier::emit("internal", "encrypted"); file.remove(); diff --git a/server/server.cpp b/server/server.cpp index eafb329..0ed7c6f 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -143,9 +143,6 @@ ServerContext::ServerContext() : rmi::Service(SOCKET_PATH), currentRequests(0), setPrivilegeChecker(std::bind(&ServerContext::checkPeerPrivilege, this, _1, _2)); - expose(this, "", (runtime::FileDescriptor)(ServerContext::registerNotificationSubscriber)(std::string)); - expose(this, "", (int)(ServerContext::unregisterNotificationSubscriber)(std::string, int)); - keys.reset(new KeyServer(*this)); secureErase.reset(new SecureEraseServer(*this)); @@ -167,6 +164,8 @@ ServerContext::ServerContext() : rmi::Service(SOCKET_PATH), currentRequests(0), if (dbusOwnerId == 0) throw runtime::Exception("Dbus failed to own name"); + EventNotifier::init(); + std::thread timerThread(&ServerContext::timerFunc, this); timerThread.detach(); } @@ -203,32 +202,4 @@ bool ServerContext::checkPeerPrivilege(const rmi::Credentials& cred, const std:: return true; } -runtime::FileDescriptor ServerContext::registerNotificationSubscriber(const std::string& name) -{ - INFO(SINK, "registerNotificationSubscriber"); - INFO(SINK, name); - - RequestLifetime rl(*this); - - int fd = subscribeNotification(name); - - /** - * Set @ label so that smack_file_receive() in kernel succeeds in checking - * 'w' access between the client and the IPOUT of the socket. - */ - if (smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) { - ERROR(SINK, "Setting IPOUT label failed"); - throw runtime::Exception("Setting IPOUT label failed"); - } - - return runtime::FileDescriptor(fd, true); -} - -int ServerContext::unregisterNotificationSubscriber(const std::string& name, int id) -{ - RequestLifetime rl(*this); - - return unsubscribeNotification(name, id); -} - } // namespace ode diff --git a/server/server.h b/server/server.h index b9ef3f3..d7bbb3f 100644 --- a/server/server.h +++ b/server/server.h @@ -26,6 +26,8 @@ #include #include +#include "event.h" + namespace ode { class SecureEraseServer; @@ -41,9 +43,6 @@ public: bool checkPeerPrivilege(const rmi::Credentials& cred, const std::string& privilege); - runtime::FileDescriptor registerNotificationSubscriber(const std::string& name); - int unregisterNotificationSubscriber(const std::string& name, int id); - void requestStarted(); void requestFinished(); -- 2.7.4