From cb7d424de32b25e6109d209ead255d73ea6cddae Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 29 Jun 2017 18:20:35 +0900 Subject: [PATCH] Align with the subdivided IService interfaces Change-Id: I64b3b0857433e53fd6f8dc89ef16a38b197449c6 Signed-off-by: Mu-Woong Lee --- src/server/ActiveUserMonitor.cpp | 85 +++++++--------- src/server/ActiveUserMonitor.h | 20 ++-- src/server/Credential.cpp | 2 +- src/server/ServerMain.cpp | 17 +--- src/server/ServiceLoader.cpp | 73 ++++++++++---- src/server/ServiceLoader.h | 33 ++---- src/server/ServiceRunner.cpp | 167 ++++++++++++++++++++++--------- src/server/ServiceRunner.h | 60 ++++++++--- 8 files changed, 279 insertions(+), 178 deletions(-) diff --git a/src/server/ActiveUserMonitor.cpp b/src/server/ActiveUserMonitor.cpp index 999fd1b..4110d68 100644 --- a/src/server/ActiveUserMonitor.cpp +++ b/src/server/ActiveUserMonitor.cpp @@ -16,17 +16,16 @@ #include #include +#include "ServiceLoader.h" #include "ActiveUserMonitor.h" #define ROOT_UID 0 using namespace ctx; -ActiveUserMonitor::ActiveUserMonitor() : +ActiveUserMonitor::ActiveUserMonitor(ServiceLoader* svcLoader) : + __serviceLoader(svcLoader), __connection(NULL), - __activateUser(NULL), - __deactivateUser(NULL), - __activeUid(ROOT_UID), __userNewSignalId(0), __userRemovedSignalId(0), __newClientSignalId(0) @@ -37,11 +36,9 @@ ActiveUserMonitor::~ActiveUserMonitor() { } -void ActiveUserMonitor::start(GDBusConnection* conn, uid_cb_t activateUser, uid_cb_t deactivateUser) +void ActiveUserMonitor::start(GDBusConnection* conn) { __connection = conn; - __activateUser = activateUser; - __deactivateUser = deactivateUser; __userNewSignalId = g_dbus_connection_signal_subscribe(__connection, NULL, "org.freedesktop.systemd1.Manager", "UserSessionStartupFinished", NULL, @@ -67,28 +64,13 @@ void ActiveUserMonitor::__onUserSessionStarted(GDBusConnection* conn, const gcha const gchar* path, const gchar* iface, const gchar* name, GVariant* param, gpointer userData) { - uint32_t uid = 0; - guint64 uid64 = 0; - - g_variant_get_child(param, 0, "t", &uid64); - uid = static_cast(uid64); + guint64 uid = 0; + g_variant_get_child(param, 0, "t", &uid); + IF_FAIL_VOID_TAG(uid != 0, _W, "UID == 0"); - IF_FAIL_VOID_TAG(uid > 0, _W, "UID == 0"); - - _D("UID: %u", uid); + _D("UID: %llu", uid); - ActiveUserMonitor* monitor = static_cast(userData); - - if (monitor->__activeUid == uid) - return; - - if (monitor->__activeUid > ROOT_UID) { - _W("Over-activation of the user %u", uid); - monitor->__deactivateUser(monitor->__activeUid); - } - - monitor->__activateUser(uid); - monitor->__activeUid = uid; + static_cast(userData)->__add(static_cast(uid)); } void ActiveUserMonitor::__onUserRemoved(GDBusConnection* conn, const gchar* sender, @@ -97,45 +79,48 @@ void ActiveUserMonitor::__onUserRemoved(GDBusConnection* conn, const gchar* send { uint32_t uid = 0; g_variant_get_child(param, 0, "u", &uid); - IF_FAIL_VOID_TAG(uid > 0, _W, "UID == 0"); + IF_FAIL_VOID_TAG(uid != 0, _W, "UID == 0"); _D("UID: %u", uid); - ActiveUserMonitor* monitor = static_cast(userData); - - if (monitor->__activeUid == ROOT_UID) { - _W("No active user"); - return; - } - - if (monitor->__activeUid != uid) { - _W("Mismatched uid"); - } - - monitor->__deactivateUser(uid); - monitor->__activeUid = ROOT_UID; + static_cast(userData)->__remove(static_cast(uid)); } void ActiveUserMonitor::__onNewClient(GDBusConnection* conn, const gchar* sender, const gchar* path, const gchar* iface, const gchar* name, GVariant* param, gpointer userData) { - _D(GREEN("A new ServiceProxy signaled")); + _D(GREEN("A new ServiceProxy(%s) has been created."), sender); ActiveUserMonitor* monitor = static_cast(userData); - IF_FAIL_VOID(monitor->__activeUid == ROOT_UID); + IF_FAIL_VOID(monitor->__uids.empty()); uid_t* users = NULL; - int numUsers = sd_get_active_uids(&users); - IF_FAIL_VOID(numUsers > 0); + int numUsers = sd_get_uids(&users); + + for (int i = 0; i < numUsers; ++i) { + monitor->__add(users[i]); + } - uid_t activeUid = users[0]; g_free(users); +} - IF_FAIL_VOID(activeUid != ROOT_UID); +void ActiveUserMonitor::__add(uid_t uid) +{ + if (__uids.find(uid) != __uids.end()) + return; + + __serviceLoader->startUser(uid); + __serviceLoader->notifyUserNew(uid); + __uids.insert(uid); +} - _D("UID: %u", monitor->__activeUid); +void ActiveUserMonitor::__remove(uid_t uid) +{ + if (__uids.find(uid) == __uids.end()) + return; - monitor->__activeUid = activeUid; - monitor->__activateUser(activeUid); + __serviceLoader->stopUser(uid); + __serviceLoader->notifyUserRemoved(uid); + __uids.erase(uid); } diff --git a/src/server/ActiveUserMonitor.h b/src/server/ActiveUserMonitor.h index d84fc9c..a4ea2c2 100644 --- a/src/server/ActiveUserMonitor.h +++ b/src/server/ActiveUserMonitor.h @@ -17,19 +17,19 @@ #ifndef __CONTEXT_ACTIVE_USER_MONITOR_H__ #define __CONTEXT_ACTIVE_USER_MONITOR_H__ +#include #include namespace ctx { - class ActiveUserMonitor { - - typedef void (*uid_cb_t)(uid_t); + class ServiceLoader; + class ActiveUserMonitor { public: - ActiveUserMonitor(); + ActiveUserMonitor(ServiceLoader* svcLoader); ~ActiveUserMonitor(); - void start(GDBusConnection* conn, uid_cb_t activateUser, uid_cb_t deactivateUser); + void start(GDBusConnection* conn); void stop(); private: @@ -45,13 +45,17 @@ namespace ctx { const gchar* path, const gchar* iface, const gchar* name, GVariant* param, gpointer userData); + void __add(uid_t uid); + void __remove(uid_t uid); + + ServiceLoader* __serviceLoader; GDBusConnection* __connection; - uid_cb_t __activateUser; - uid_cb_t __deactivateUser; - uid_t __activeUid; + guint __userNewSignalId; guint __userRemovedSignalId; guint __newClientSignalId; + + std::set __uids; }; } diff --git a/src/server/Credential.cpp b/src/server/Credential.cpp index 5bf2e14..445e569 100644 --- a/src/server/Credential.cpp +++ b/src/server/Credential.cpp @@ -154,5 +154,5 @@ const std::string& Credential::getClientId() const bool Credential::isSystem() const { - return util::isSystemUid(__uid); + return util::isSystem(__uid); } diff --git a/src/server/ServerMain.cpp b/src/server/ServerMain.cpp index a1d002e..3738a00 100644 --- a/src/server/ServerMain.cpp +++ b/src/server/ServerMain.cpp @@ -64,22 +64,12 @@ void MainLoop::stop() } static ServiceLoader __serviceLoader; -static ActiveUserMonitor __activeUserMonitor; +static ActiveUserMonitor __activeUserMonitor(&__serviceLoader); static AlarmInitializer __alarmInit; -static void __activateUser(uid_t uid) -{ - __serviceLoader.startUser(uid); -} - -static void __deactivateUser(uid_t uid) -{ - __serviceLoader.stopUser(); -} - static void __startService(GDBusConnection* conn) { - __activeUserMonitor.start(conn, __activateUser, __deactivateUser); + __activeUserMonitor.start(conn); _I("Loading services"); if (!__serviceLoader.load(conn)) { @@ -96,8 +86,7 @@ static gboolean __stopService(gpointer data) __activeUserMonitor.stop(); _I("Unloading services"); - __serviceLoader.stopUser(); - __serviceLoader.stopSystem(); + __serviceLoader.stopAll(); MainLoop::stop(); return G_SOURCE_REMOVE; diff --git a/src/server/ServiceLoader.cpp b/src/server/ServiceLoader.cpp index 90f8ef1..70b2a6e 100644 --- a/src/server/ServiceLoader.cpp +++ b/src/server/ServiceLoader.cpp @@ -22,12 +22,9 @@ #include "ServiceLoader.h" -#define ROOT_UID 0 - using namespace ctx; -ServiceLoader::ServiceLoader() : - __activeUser(ROOT_UID) +ServiceLoader::ServiceLoader() { } @@ -41,6 +38,31 @@ ServiceLoader::~ServiceLoader() } } +template +void ServiceLoader::__create(GDBusConnection* conn) +{ + IService* svc = NULL; + + try { + svc = new ServiceType(); + } catch (const std::runtime_error& e) { + _I(YELLOW("%s"), e.what()); + return; + } + + ServiceRunner* runner = NULL; + + if (dynamic_cast(svc)) { + runner = new UserServiceRunner(conn, svc); + __userServices.push_back(runner); + } else { + runner = new SystemServiceRunner(conn, svc); + __systemServices.push_back(runner); + } + + svc->setServiceRunner(runner); +} + bool ServiceLoader::load(GDBusConnection* conn) { __create(conn); @@ -67,36 +89,45 @@ void ServiceLoader::stopSystem() void ServiceLoader::startUser(uid_t uid) { - IF_FAIL_VOID(__activeUser != uid); - _I("Starting services for %u", static_cast(uid)); - - util::setActiveUid(uid); - - for (auto& runner : __userServices) { - runner->start(); + if (util::isNormalUser(uid)) { + for (auto& runner : __userServices) { + runner->stop(); + runner->start(uid); + } } +} - for (auto& runner : __systemServices) { - runner->notifyUserNew(); +void ServiceLoader::stopUser(uid_t uid) +{ + if (util::isNormalUser(uid)) { + for (auto& runner : __userServices) { + runner->stop(); + } } - __activeUser = uid; } -void ServiceLoader::stopUser() +void ServiceLoader::stopAll() { - IF_FAIL_VOID(__activeUser != ROOT_UID); - _I("Stopping services for %u", static_cast(__activeUser)); - for (auto& runner : __userServices) { runner->stop(); } - util::setActiveUid(ROOT_UID); + for (auto& runner : __systemServices) { + runner->stop(); + } +} +void ServiceLoader::notifyUserNew(uid_t uid) +{ for (auto& runner : __systemServices) { - runner->notifyUserRemoved(); + runner->notifyUserNew(uid); } +} - __activeUser = ROOT_UID; +void ServiceLoader::notifyUserRemoved(uid_t uid) +{ + for (auto& runner : __systemServices) { + runner->notifyUserRemoved(uid); + } } diff --git a/src/server/ServiceLoader.h b/src/server/ServiceLoader.h index ef85039..cdf426d 100644 --- a/src/server/ServiceLoader.h +++ b/src/server/ServiceLoader.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "ServiceRunner.h" #include "ServiceClient.h" @@ -32,36 +33,22 @@ namespace ctx { bool load(GDBusConnection* conn); - void startUser(uid_t uid); - void stopUser(); void startSystem(); void stopSystem(); - private: - uid_t __activeUser; - std::vector __userServices; - std::vector __systemServices; + void startUser(uid_t uid); + void stopUser(uid_t uid); - template void __create(GDBusConnection* conn) - { - IService* svc = NULL; + void stopAll(); - try { - svc = new ServiceType(); - } catch (const std::runtime_error& e) { - _I(YELLOW("%s"), e.what()); - return; - } + void notifyUserNew(uid_t uid); + void notifyUserRemoved(uid_t uid); - ServiceRunner* runner = new ServiceRunner(conn, svc); - svc->setServiceRunner(runner); + private: + std::vector __userServices; + std::vector __systemServices; - if (svc->isUserService()) { - __userServices.push_back(runner); - } else { - __systemServices.push_back(runner); - } - } + template void __create(GDBusConnection* conn); }; } diff --git a/src/server/ServiceRunner.cpp b/src/server/ServiceRunner.cpp index b35859d..f29edbc 100644 --- a/src/server/ServiceRunner.cpp +++ b/src/server/ServiceRunner.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ -#include +#include +#include +#include +#include #include "MethodCall.h" #include "ServiceClient.h" #include "ServiceRunner.h" @@ -22,16 +25,17 @@ using namespace ctx; ServiceRunner::ServiceRunner(GDBusConnection* conn, IService* service) : - __service(service), - __started(false), + serviceInstance(service), + started(false), + __uid(0), __connection(conn), __objPath(CTX_DBUS_PATH "/"), __interface(CTX_DBUS_IFACE "."), __nodeInfo(NULL), __registrationId(0) { - __objPath += __service->getServiceName(); - __interface += __service->getServiceName(); + __objPath += serviceInstance->getServiceName(); + __interface += serviceInstance->getServiceName(); } ServiceRunner::~ServiceRunner() @@ -50,33 +54,34 @@ GDBusConnection* ServiceRunner::getConnection() IService* ServiceRunner::getService() { - return __service; + return serviceInstance; } -bool ServiceRunner::start() +bool ServiceRunner::start(uid_t uid) { - IF_FAIL_RETURN(!__started, true); + IF_FAIL_RETURN(!started, true); - _I(CYAN("Starting '%s'"), __service->getServiceName()); + _I(CYAN("Starting '%s'"), serviceInstance->getServiceName()); - if (!__init()) { + if (!__init(uid)) { _E("Starting failed"); - __release(); + __release(uid); return false; } - __started = true; + started = true; + __uid = uid; return true; } void ServiceRunner::stop() { - IF_FAIL_VOID(__started); - __started = false; + IF_FAIL_VOID(started); + started = false; - _I(PURPLE("Stopping '%s'"), __service->getServiceName()); + _I(PURPLE("Stopping '%s'"), serviceInstance->getServiceName()); - __release(); + __release(__uid); } void ServiceRunner::publish(const std::string& busName, const std::string& signalName, GVariant* param) @@ -88,19 +93,7 @@ void ServiceRunner::publish(const std::string& busName, const std::string& signa HANDLE_GERROR(gerr); } -void ServiceRunner::notifyUserNew() -{ - if (__started) - __service->onUserActivated(); -} - -void ServiceRunner::notifyUserRemoved() -{ - if (__started) - __service->onUserDeactivated(); -} - -bool ServiceRunner::__init() +bool ServiceRunner::__init(uid_t uid) { GError* gerr = NULL; GDBusInterfaceVTable vtable; @@ -110,7 +103,7 @@ bool ServiceRunner::__init() vtable.set_property = NULL; std::string introspection("" + __service->getMethodSpecs() + ""; + introspection += __interface + "'>" + serviceInstance->getMethodSpecs() + ""; __nodeInfo = g_dbus_node_info_new_for_xml(introspection.c_str(), NULL); IF_FAIL_RETURN_TAG(__nodeInfo, false, _E, "NodeInfo creation failed"); @@ -120,10 +113,10 @@ bool ServiceRunner::__init() HANDLE_GERROR(gerr); IF_FAIL_RETURN_TAG(__registrationId > 0, false, _E, "Object registration failed"); - return __service->prepare(); + return __prepare(uid); } -void ServiceRunner::__release() +void ServiceRunner::__release(uid_t uid) { for (auto iter = __clients.begin(); iter != __clients.end(); ++iter) { iter->second.client->onDisconnected(); @@ -132,7 +125,7 @@ void ServiceRunner::__release() __clients.clear(); - __service->cleanup(); + __cleanup(uid); if (__registrationId > 0) g_dbus_connection_unregister_object(__connection, __registrationId); @@ -146,16 +139,14 @@ void ServiceRunner::__onMethodCalled(GDBusConnection* conn, const gchar* sender, GVariant* param, GDBusMethodInvocation* invocation, gpointer userData) { ServiceRunner* runner = static_cast(userData); - runner->__onMethodCalled(sender, name, param, invocation); -} -void ServiceRunner::__onMethodCalled(const std::string& sender, - const std::string& name, GVariant* param, GDBusMethodInvocation* invocation) -{ - _I("'%s' called '%s.%s'", sender.c_str(), __service->getServiceName(), name.c_str()); + _I("'%s' called '%s.%s'", sender, iface, name); - ServiceClient* client = __getClient(sender); - IF_FAIL_VOID(client); + ServiceClient* client = runner->__getClient(sender); + if (!client) { + g_dbus_method_invocation_return_error_literal(invocation, CTX_ERROR_DOMAIN, E_SUPPORT, ""); + return; + } client->onMethodCalled(new MethodCall(client, name, param, invocation)); } @@ -167,15 +158,12 @@ ServiceClient* ServiceRunner::__getClient(const std::string& busName) if (iter != __clients.end()) return iter->second.client; - ServiceClient* client = new ServiceClient(this, busName); - if (!client->isVerified()) { - delete client; - return NULL; - } + ServiceClient* client = __createClient(busName); + IF_FAIL_RETURN(client, NULL); - IMethodCallHandler* callHandler = __service->createMethodCallHandler(client); + IMethodCallHandler* callHandler = serviceInstance->createMethodCallHandler(client); if (!callHandler) { - _E("This cannot be NULL."); + _E("%s's method call handler cannot be NULL.", serviceInstance->getServiceName()); delete client; return NULL; } @@ -198,7 +186,7 @@ void ServiceRunner::__onNameOwnerChanged(GDBusConnection* conn, const gchar* sen void ServiceRunner::__removeClient(const std::string& busName) { - _I("'%s' lost '%s'", __service->getServiceName(), busName.c_str()); + _I("'%s' lost '%s'", serviceInstance->getServiceName(), busName.c_str()); auto iter = __clients.find(busName); IF_FAIL_VOID(iter != __clients.end()); @@ -222,3 +210,84 @@ void ServiceRunner::__unwatch(unsigned int watchId) { g_dbus_connection_signal_unsubscribe(__connection, watchId); } + + +SystemServiceRunner::SystemServiceRunner(GDBusConnection* conn, IService* service) : + ServiceRunner(conn, service) +{ +} + +void SystemServiceRunner::notifyUserNew(uid_t uid) +{ + if (started) + static_cast(serviceInstance)->onUserActivated(uid); +} + +void SystemServiceRunner::notifyUserRemoved(uid_t uid) +{ + if (started) + static_cast(serviceInstance)->onUserDeactivated(uid); +} + +bool SystemServiceRunner::__prepare(uid_t uid) +{ + return static_cast(serviceInstance)->prepare(); +} + +void SystemServiceRunner::__cleanup(uid_t uid) +{ + static_cast(serviceInstance)->cleanup(); +} + +ServiceClient* SystemServiceRunner::__createClient(const std::string& busName) +{ + ServiceClient* client = new ServiceClient(this, busName); + + if (!client->isVerified()) { + delete client; + return NULL; + } + + return client; +} + +UserServiceRunner::UserServiceRunner(GDBusConnection* conn, IService* service) : + ServiceRunner(conn, service) +{ +} + +void UserServiceRunner::notifyUserNew(uid_t uid) +{ +} + +void UserServiceRunner::notifyUserRemoved(uid_t uid) +{ +} + +bool UserServiceRunner::__prepare(uid_t uid) +{ + return static_cast(serviceInstance)->prepare(uid); +} + +void UserServiceRunner::__cleanup(uid_t uid) +{ + static_cast(serviceInstance)->cleanup(uid); +} + +ServiceClient* UserServiceRunner::__createClient(const std::string& busName) +{ + ServiceClient* client = new ServiceClient(this, busName); + + if (!client->isVerified()) { + delete client; + return NULL; + } + + if (!util::isNormalUser(client->getUid())) { + _W("%s does not support container users.", serviceInstance->getServiceName()); + delete client; + return NULL; + } + + return client; +} diff --git a/src/server/ServiceRunner.h b/src/server/ServiceRunner.h index b51fcd9..0e7cf3d 100644 --- a/src/server/ServiceRunner.h +++ b/src/server/ServiceRunner.h @@ -29,14 +29,13 @@ namespace ctx { class ServiceRunner : public IServiceRunner { public: - ServiceRunner(GDBusConnection* conn, IService* service); - ~ServiceRunner(); + virtual ~ServiceRunner(); - bool start(); - void stop(); + virtual void notifyUserNew(uid_t uid) = 0; + virtual void notifyUserRemoved(uid_t uid) = 0; - void notifyUserNew(); - void notifyUserRemoved(); + bool start(uid_t uid = 0); + void stop(); void publish(const std::string& busName, const std::string& signalName, GVariant* param); @@ -44,6 +43,12 @@ namespace ctx { GDBusConnection* getConnection(); IService* getService(); + protected: + ServiceRunner(GDBusConnection* conn, IService* service); + + IService* serviceInstance; + bool started; + private: static void __onMethodCalled(GDBusConnection* conn, const gchar* sender, const gchar* path, const gchar* iface, const gchar* name, @@ -53,19 +58,20 @@ namespace ctx { const gchar* path, const gchar* iface, const gchar* name, GVariant* param, gpointer userData); - void __onMethodCalled(const std::string& sender, - const std::string& name, GVariant* param, GDBusMethodInvocation* invocation); + virtual bool __prepare(uid_t uid) = 0; + virtual void __cleanup(uid_t uid) = 0; - bool __init(); - void __release(); + virtual ServiceClient* __createClient(const std::string& busName) = 0; + + bool __init(uid_t uid); + void __release(uid_t uid); ServiceClient* __getClient(const std::string& busName); void __removeClient(const std::string& busName); unsigned int __watch(const std::string& busName, ServiceClient* client); void __unwatch(unsigned int watchId); - IService* __service; - bool __started; + uid_t __uid; GDBusConnection* __connection; std::string __objPath; @@ -82,6 +88,36 @@ namespace ctx { std::map __clients; }; + + class SystemServiceRunner : public ServiceRunner { + public: + SystemServiceRunner(GDBusConnection* conn, IService* service); + + void notifyUserNew(uid_t uid); + void notifyUserRemoved(uid_t uid); + + private: + bool __prepare(uid_t uid); + void __cleanup(uid_t uid); + + ServiceClient* __createClient(const std::string& busName); + }; + + + class UserServiceRunner : public ServiceRunner { + public: + UserServiceRunner(GDBusConnection* conn, IService* service); + + void notifyUserNew(uid_t uid); + void notifyUserRemoved(uid_t uid); + + private: + bool __prepare(uid_t uid); + void __cleanup(uid_t uid); + + ServiceClient* __createClient(const std::string& busName); + }; + } #endif /* __CONTEXT_SERVICE_RUNNER_H__ */ -- 2.34.1