Use dbus for event notification 09/231409/4 accepted/tizen_5.5_unified_wearable_hotfix tizen_5.5_wearable_hotfix accepted/tizen/5.5/unified/20200422.234530 accepted/tizen/5.5/unified/wearable/hotfix/20201027.112759 submit/tizen_5.5/20200422.051749 submit/tizen_5.5_wearable_hotfix/20201026.184304
authorJaemin Ryu <jm77.ryu@samsung.com>
Wed, 22 Apr 2020 01:21:46 +0000 (10:21 +0900)
committerJaemin Ryu <jm77.ryu@samsung.com>
Wed, 22 Apr 2020 04:29:50 +0000 (13:29 +0900)
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
lib/client.h
lib/ode/internal-encryption.cpp
lib/ode/luks.cpp
server/CMakeLists.txt
server/event.cpp [new file with mode: 0644]
server/event.h [new file with mode: 0644]
server/internal-encryption.cpp
server/server.cpp
server/server.h

index 435f293..7c8c286 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
-
+#include <klay/dbus/signal.h>
 #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<std::string>
-                                                       (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;
+       }
 }
index 691e96e..a07255d 100644 (file)
 
 #include <klay/rmi/client.h>
 #include <rmi/common.h>
+#include <klay/gmainloop.h>
 
 typedef std::function<void(void*)> SignalListener;
 
 typedef std::unique_ptr<rmi::Client> 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<typename ...Args>
-       int subscribeSignal(const std::string& name, const std::function<void(Args...)>& listener)
-       {
-               try {
-                       int ret = client->subscribe<Args...>(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<typename Interface, typename... Args>
        Interface createInterface(Args&&... args) noexcept
        {
@@ -69,6 +53,7 @@ public:
 
 private:
        RmiClientPtr client;
+       std::unique_ptr<ScopedGMainLoop> mainloop;
 };
 
 #endif //__ODE_CLIENT_H__
index de808c0..a69e265 100644 (file)
@@ -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);
 
index d92e50a..b878bff 100644 (file)
@@ -26,7 +26,6 @@
 using namespace ode;
 
 namespace {
-std::unique_ptr<ClientContext> 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::function<void(std::string, int, int)>cb = [callback, user_data](std::string, int op, int res) {
-               callback(static_cast<ode_luks_operation_e>(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)
index 085003a..6526204 100644 (file)
@@ -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 (file)
index 0000000..4e4cb12
--- /dev/null
@@ -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 <klay/dbus/signal.h>
+#include <klay/dbus/introspection.h>
+#include <klay/exception.h>
+
+const std::string SIGNAL_OBJECT_PATH = "/org/tizen/OnDeviceEncryption";
+const std::string SIGNAL_EVENT_INTERFACE = "org.tizen.OnDeviceEncryption.Event";
+
+const std::string manifest =
+    "<node>"
+    "   <interface name='" + SIGNAL_EVENT_INTERFACE + "'>"
+    "       <signal name='" + SIGNAL_OBJECT_PATH + "'>"
+    "           <arg type='s' name='argument'/>"
+    "       </signal>"
+    "   </interface>"
+    "</node>";
+
+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 (file)
index 0000000..08509bd
--- /dev/null
@@ -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 <string>
+
+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__
index 20449e5..a81302a 100644 (file)
@@ -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<unsigned char> &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();
 
index eafb329..0ed7c6f 100644 (file)
@@ -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
index b9ef3f3..d7bbb3f 100644 (file)
@@ -26,6 +26,8 @@
 #include <klay/file-descriptor.h>
 #include <klay/rmi/service.h>
 
+#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();