From ec5ca263074a531be721dba12af971b8da948338 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Sat, 29 Jul 2017 18:59:44 +0900 Subject: [PATCH] Implement the agent daemon Change-Id: I7542bd9f11f899574d910d9d2adbab76e6fb18dd Signed-off-by: Mu-Woong Lee --- CMakeLists.txt | 5 + packaging/context-service.spec | 10 +- packaging/contextd-agent.service | 7 +- packaging/contextd-agent.socket | 7 + src/agent/AgentDBus.cpp | 69 ++++++++++ src/agent/AgentDBus.h | 40 ++++++ src/agent/AgentMain.cpp | 36 ++++- src/agent/AgentSocket.cpp | 227 +++++++++++++++++++++++++++++++ src/agent/AgentSocket.h | 50 +++++++ src/agent/AgentUtil.cpp | 34 +++++ src/agent/AgentUtil.h | 40 ++++++ src/agent/CMakeLists.txt | 10 +- src/agent/PluginLoader.cpp | 117 ++++++++++++++++ src/agent/PluginLoader.h | 47 +++++++ src/server/CMakeLists.txt | 2 +- src/server/ServerMain.cpp | 70 +--------- src/shared/ServerBase.cpp | 76 +++++++++++ src/shared/ServerBase.h | 33 +++++ 18 files changed, 807 insertions(+), 73 deletions(-) create mode 100644 packaging/contextd-agent.socket create mode 100644 src/agent/AgentDBus.cpp create mode 100644 src/agent/AgentDBus.h create mode 100644 src/agent/AgentSocket.cpp create mode 100644 src/agent/AgentSocket.h create mode 100644 src/agent/AgentUtil.cpp create mode 100644 src/agent/AgentUtil.h create mode 100644 src/agent/PluginLoader.cpp create mode 100644 src/agent/PluginLoader.h create mode 100644 src/shared/ServerBase.cpp create mode 100644 src/shared/ServerBase.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c9d1849..549a8e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(context-service) INCLUDE(GNUInstallDirs) +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/src/shared +) + ADD_DEFINITIONS(-O2 -Wall -fPIC -fPIE -fdata-sections -ffunction-sections -fvisibility=hidden) +ADD_DEFINITIONS(-D_LIBDIR_="${LIBDIR}") ADD_DEFINITIONS(-fdiagnostics-color) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC -pie -Wl,--as-needed -Wl,--gc-sections -Wl,--print-gc-sections") SET(CMAKE_VERBOSE_MAKEFILE OFF) diff --git a/packaging/context-service.spec b/packaging/context-service.spec index 130e273..ca3b359 100644 --- a/packaging/context-service.spec +++ b/packaging/context-service.spec @@ -8,8 +8,10 @@ Source0: %{name}-%{version}.tar.gz Source1: contextd.service Source2: org.tizen.context.conf Source3: contextd-agent.service +Source4: contextd-agent.socket BuildRequires: cmake +BuildRequires: pkgconfig(libsystemd-daemon) BuildRequires: pkgconfig(libsystemd-login) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) @@ -49,7 +51,7 @@ export CXXFLAGS+=" -Wformat=2 -Wno-empty-body -fomit-frame-pointer -fno-optimize export CXXFLAGS+=" -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow" export CXXFLAGS+=" -Wnon-virtual-dtor -std=c++0x" -%cmake . +%cmake . -DLIBDIR=%{_libdir} make %{?_smp_mflags} %install @@ -62,8 +64,10 @@ ln -s ../contextd.service %{buildroot}%{_unitdir}/multi-user.target.wants/contex mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d install -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/dbus-1/system.d/ -mkdir -p %{buildroot}%{_unitdir_user} +mkdir -p %{buildroot}%{_unitdir_user}/sockets.target.wants install -m 0644 %{SOURCE3} %{buildroot}%{_unitdir_user} +install -m 0644 %{SOURCE4} %{buildroot}%{_unitdir_user} +ln -s ../contextd-agent.socket %{buildroot}%{_unitdir_user}/sockets.target.wants/contextd-agent.socket %files %manifest packaging/%{name}.manifest @@ -77,4 +81,6 @@ install -m 0644 %{SOURCE3} %{buildroot}%{_unitdir_user} %manifest packaging/%{name}.manifest %{_bindir}/contextd-agent %{_unitdir_user}/contextd-agent.service +%{_unitdir_user}/contextd-agent.socket +%{_unitdir_user}/*/contextd-agent.socket %license LICENSE diff --git a/packaging/contextd-agent.service b/packaging/contextd-agent.service index 8eb83c4..4e6819c 100644 --- a/packaging/contextd-agent.service +++ b/packaging/contextd-agent.service @@ -2,5 +2,10 @@ Description=Contextual Service Framework User-Level Agent Daemon [Service] -Type=simple +Type=notify ExecStart=/usr/bin/contextd-agent +Sockets=contextd-agent.socket +Restart=no + +[Install] +WantedBy=sockets.target diff --git a/packaging/contextd-agent.socket b/packaging/contextd-agent.socket new file mode 100644 index 0000000..71de9ef --- /dev/null +++ b/packaging/contextd-agent.socket @@ -0,0 +1,7 @@ +[Unit] +Description=Context-Agent Socket + +[Socket] +ListenStream=/run/user_ext/%U/.contextd-agent.socket +Service=contextd-agent.service +Accept=false diff --git a/src/agent/AgentDBus.cpp b/src/agent/AgentDBus.cpp new file mode 100644 index 0000000..fa952b0 --- /dev/null +++ b/src/agent/AgentDBus.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include "AgentDBus.h" + +using namespace ctx; + +AgentDBus::AgentDBus() : + __connection(NULL) +{ + if (!__init()) + throw std::runtime_error("DBus connection failed"); + + _I("Connection established (%s)", g_dbus_connection_get_unique_name(__connection)); +} + +AgentDBus::~AgentDBus() +{ + __release(); +} + +GDBusConnection* AgentDBus::getConnection() +{ + return __connection; +} + +bool AgentDBus::__init() +{ + GError *gerr = NULL; + gchar *addr = NULL; + + addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(addr, false, _E, "Getting address failed"); + + __connection = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(__connection, false, _E, "Connection failed"); + + return true; +} + +void AgentDBus::__release() +{ + if (__connection) { + g_dbus_connection_flush_sync(__connection, NULL, NULL); + g_dbus_connection_close_sync(__connection, NULL, NULL); + g_object_unref(__connection); + } + + _I("Connection released"); +} diff --git a/src/agent/AgentDBus.h b/src/agent/AgentDBus.h new file mode 100644 index 0000000..345cb3e --- /dev/null +++ b/src/agent/AgentDBus.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CONTEXT_AGENT_DBUS_H__ +#define __CONTEXT_AGENT_DBUS_H__ + +#include + +namespace ctx { + + class AgentDBus { + public: + AgentDBus(); + ~AgentDBus(); + + GDBusConnection* getConnection(); + + private: + bool __init(); + void __release(); + + GDBusConnection* __connection; + }; + +} + +#endif diff --git a/src/agent/AgentMain.cpp b/src/agent/AgentMain.cpp index fc1dc8d..fd271be 100644 --- a/src/agent/AgentMain.cpp +++ b/src/agent/AgentMain.cpp @@ -14,9 +14,43 @@ * limitations under the License. */ +#include #include +#include -int main(int argc, char* argv[]) +#include +#include "AgentDBus.h" +#include "AgentUtil.h" +#include "PluginLoader.h" +#include "AgentSocket.h" + +using namespace ctx; + +static MainLoop __mainLoop; + +static void __on_signal(int signum) +{ + _I(YELLOW("SIGNAL-%d: '%s'"), signum, strsignal(signum)); + __mainLoop.stop(); +} + +int main(int argc, char **argv) { + std::signal(SIGINT, __on_signal); + std::signal(SIGHUP, __on_signal); + std::signal(SIGTERM, __on_signal); + std::signal(SIGQUIT, __on_signal); + + AgentDBus agentDBus; + AgentUtil agentUtil(agentDBus); + PluginLoader pluginLoader(agentUtil); + AgentSocket agentSocket(pluginLoader); + + sd_notify(0, "READY=1"); + + __mainLoop.start(); + + sd_notify(0, "STOPPING=1"); + return EXIT_SUCCESS; } diff --git a/src/agent/AgentSocket.cpp b/src/agent/AgentSocket.cpp new file mode 100644 index 0000000..e8d45b9 --- /dev/null +++ b/src/agent/AgentSocket.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include +#include +#include +#include +#include "PluginLoader.h" +#include "AgentSocket.h" + +#define PATH_LENGTH 48 +#define TERM_MSG_ID 0xFFFF + +using namespace ctx; + +struct CommandInfo { + PluginLoader* pluginLoader; + uint16_t id; + uint8_t length; + void* command; + + CommandInfo(PluginLoader* loader, uint16_t i, uint8_t len, char* cmd) : + pluginLoader(loader), id(i), length(len), command(NULL) + { + command = malloc(length); + + if (!command) + throw std::bad_alloc(); + + memcpy(command, cmd, length); + } + + ~CommandInfo() + { + free(command); + } +}; + +static gboolean __send_command(gpointer data) +{ + CommandInfo* info = static_cast(data); + + info->pluginLoader->send(info->id, info->length, info->command); + + delete info; + + return G_SOURCE_REMOVE; +} + +static bool __set_close_on_exec(int fd) +{ + if (::fcntl(fd, F_SETFL, FD_CLOEXEC) == -1) + return false; + + return true; +} + +static int __get_socket_fd(const char* path) +{ + int n = sd_listen_fds(0); + IF_FAIL_RETURN_TAG(n > 0, E_ACCESS, _E, "sd_listen_fds() failed"); + + for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) { + if (sd_is_socket_unix(fd, SOCK_STREAM, 1, path, 0) > 0) { + __set_close_on_exec(fd); + return fd; + } + } + + return E_ACCESS; +} + +AgentSocket::AgentSocket(PluginLoader& loader) : + __sockFd(-1), + __listening(false), + __listeningThread(NULL), + __pluginLoader(loader) +{ + if (!__init()) { + __release(); + throw std::runtime_error("Socket connection failed"); + } + + _I("Listening..."); +} + +AgentSocket::~AgentSocket() +{ + __release(); +} + +bool AgentSocket::__init() +{ + char path[PATH_LENGTH]; + g_snprintf(path, PATH_LENGTH, CTX_AGENT_SOCKET, static_cast(getuid())); + + _D("Socket Path: %s", path); + + __sockFd = __get_socket_fd(path); + IF_FAIL_RETURN_TAG(__sockFd > 0, false, _E, "Failed to get the socket fd"); + + __listening.store(true); + __listeningThread = g_thread_new(NULL, __listen, this); + IF_FAIL_RETURN_TAG(__listeningThread, false, _E, "Thread creation failed"); + + return true; +} + +gpointer AgentSocket::__listen(gpointer data) +{ + static_cast(data)->__listen(); + return NULL; +} + +void AgentSocket::__listen() +{ + int msgsock = 0; + + while (__listening.load()) { + msgsock = accept(__sockFd, 0, 0); + + if (msgsock < 0) { + _D("accept() failed"); + continue; + } + + if (!__readCommand(msgsock)) { + close(msgsock); + break; + } + + close(msgsock); + } +} + +bool AgentSocket::__readCommand(int msgsock) +{ + uint16_t id = 0; + uint8_t length = 0; + int rval = 0; + char buf[CTX_AGENT_COMMAND_LIMIT] = {0}; + + rval = read(msgsock, &id, sizeof(id)); + IF_FAIL_RETURN_TAG(rval == sizeof(id), false, _E, "read() failed"); + + if (id == TERM_MSG_ID) { + _D("Stop listening..."); + return false; + } + + rval = read(msgsock, &length, sizeof(length)); + IF_FAIL_RETURN_TAG(rval == sizeof(length), false, _E, "read() failed"); + + rval = read(msgsock, buf, length); + IF_FAIL_RETURN_TAG(rval == static_cast(length), false, _E, "read() failed"); + + + buf[length] = '\0'; + + CommandInfo* info = new CommandInfo(&__pluginLoader, id, length, buf); + g_idle_add(__send_command, info); + + return true; +} + +void AgentSocket::__release() +{ + if (!__listening.load()) + return; + + __listening.store(false); + __terminate(); + + if (__listeningThread) + g_thread_join(__listeningThread); + + close(__sockFd); +} + +bool AgentSocket::__terminate() +{ + int sock = -1; + sockaddr_un addr; + char path[PATH_LENGTH]; + const uint16_t termMsg = TERM_MSG_ID; + + g_snprintf(path, PATH_LENGTH, CTX_AGENT_SOCKET, static_cast(getuid())); + IF_FAIL_RETURN_TAG(strlen(path) < sizeof(addr.sun_path), false, _E, "Invalid path"); + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + IF_FAIL_RETURN_TAG(sock > 0, false, _E, "socket creation failed"); + + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof(addr.sun_path)); + addr.sun_path[sizeof(path)] = '\0'; + + if (connect(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { + close(sock); + _E("Connection failed"); + return false; + } + + if (write(sock, &termMsg, sizeof(termMsg)) < 0) { + close(sock); + _E("Sending failed"); + return false; + } + + close(sock); + return true; +} diff --git a/src/agent/AgentSocket.h b/src/agent/AgentSocket.h new file mode 100644 index 0000000..d3f1ebd --- /dev/null +++ b/src/agent/AgentSocket.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CONTEXT_AGENT_SOCKET_H__ +#define __CONTEXT_AGENT_SOCKET_H__ + +#include +#include + +namespace ctx { + + class PluginLoader; + + class AgentSocket { + public: + AgentSocket(PluginLoader& loader); + ~AgentSocket(); + + private: + bool __init(); + void __release(); + + void __listen(); + bool __readCommand(int msgsock); + bool __terminate(); + + static gpointer __listen(gpointer data); + + int __sockFd; + std::atomic_bool __listening; + GThread* __listeningThread; + PluginLoader& __pluginLoader; + }; + +} + +#endif diff --git a/src/agent/AgentUtil.cpp b/src/agent/AgentUtil.cpp new file mode 100644 index 0000000..a7bdee7 --- /dev/null +++ b/src/agent/AgentUtil.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "AgentDBus.h" +#include "AgentUtil.h" + +using namespace ctx; + +AgentUtil::AgentUtil(AgentDBus& agentDBus) : + __agentDBus(agentDBus) +{ +} + +AgentUtil::~AgentUtil() +{ +} + +GDBusConnection* AgentUtil::getDBusConnection() +{ + return __agentDBus.getConnection(); +} diff --git a/src/agent/AgentUtil.h b/src/agent/AgentUtil.h new file mode 100644 index 0000000..008162f --- /dev/null +++ b/src/agent/AgentUtil.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CONTEXT_AGENT_UTIL_H__ +#define __CONTEXT_AGENT_UTIL_H__ + +#include +#include + +namespace ctx { + + class AgentDBus; + + class AgentUtil : public IAgentUtil { + public: + AgentUtil(AgentDBus& agentDBus); + ~AgentUtil(); + + GDBusConnection* getDBusConnection(); + + private: + AgentDBus& __agentDBus; + }; + +} + +#endif diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index 69d426e..cbe2063 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -2,9 +2,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(target "contextd-agent") -SET(DEPS glib-2.0 gio-2.0 gmodule-2.0 dlog capi-base-common) +SET(DEPS glib-2.0 gio-2.0 gmodule-2.0 libsystemd-daemon dlog capi-base-common) -FILE(GLOB_RECURSE SRCS *.cpp) +SET(INCDIR "${CMAKE_INSTALL_INCLUDEDIR}/context-service") + +INCLUDE_DIRECTORIES( + ${CMAKE_INSTALL_PREFIX}/${INCDIR}/private +) + +FILE(GLOB SRCS *.cpp ../shared/*.cpp) MESSAGE("Sources: ${SRCS}") INCLUDE(FindPkgConfig) diff --git a/src/agent/PluginLoader.cpp b/src/agent/PluginLoader.cpp new file mode 100644 index 0000000..c49b617 --- /dev/null +++ b/src/agent/PluginLoader.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include +#include +#include "AgentUtil.h" +#include "PluginLoader.h" + +#define PLUGIN_DIR _LIBDIR_ "/" CTX_AGENT_PLUGIN_DIR + +using namespace ctx; + +PluginLoader::PluginLoader(AgentUtil& agentUtil) : + __agentUtil(agentUtil) +{ + if (!__load()) { + __unload(); + throw std::runtime_error("Plugin loading failed"); + } + + _I("%u plugins loaded", __plugins.size()); +} + +PluginLoader::~PluginLoader() +{ + __unload(); +} + +void PluginLoader::send(uint16_t id, uint8_t length, const void* command) +{ + for (auto& agent : __plugins) { + if (agent->getId() == id) { + agent->doAction(length, command); + return; + } + } + + _W("Agent not found"); +} + +bool PluginLoader::__load() +{ + DIR* dir = NULL; + struct dirent* entry = NULL; + struct stat fileStat; + + _D("Scanning %s", PLUGIN_DIR); + + dir = opendir(PLUGIN_DIR); + IF_FAIL_RETURN_TAG(dir, false, _E, "Failed to open: %s", PLUGIN_DIR); + + while ((entry = readdir(dir))) { + std::string filePath(PLUGIN_DIR "/"); + filePath.append(entry->d_name); + + if (lstat(filePath.c_str(), &fileStat) != 0) + continue; + + if (!S_ISREG(fileStat.st_mode)) + continue; + + if (!__load(filePath)) { + closedir(dir); + _E("Failed to load %s", filePath.c_str()); + return false; + } + } + + closedir(dir); + return true; +} + +bool PluginLoader::__load(const std::string& filePath) +{ + _D("Loading plugins from %s", filePath.c_str()); + + GModule *soHandle = g_module_open(filePath.c_str(), G_MODULE_BIND_LAZY); + IF_FAIL_RETURN_TAG(soHandle, false, _E, "%s", g_module_error()); + + create_plugins_t createPlugins; + if (!g_module_symbol(soHandle, CTX_AGENT_CREATE_FUNC_SYM, (gpointer*)&createPlugins) || !createPlugins) { + _E("%s", g_module_error()); + g_module_close(soHandle); + return false; + } + + IAgentPlugin** plugins = createPlugins(&__agentUtil); + for (int i = 0; plugins[i] != NULL; ++i) { + __plugins.push_back(plugins[i]); + } + + return true; +} + +void PluginLoader::__unload() +{ + for (auto& plugin : __plugins) { + delete plugin; + } + + __plugins.clear(); +} diff --git a/src/agent/PluginLoader.h b/src/agent/PluginLoader.h new file mode 100644 index 0000000..557c22a --- /dev/null +++ b/src/agent/PluginLoader.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CONTEXT_AGENT_PLUGIN_LOADER_H__ +#define __CONTEXT_AGENT_PLUGIN_LOADER_H__ + +#include +#include +#include +#include + +namespace ctx { + + class AgentUtil; + + class PluginLoader { + public: + PluginLoader(AgentUtil& agentUtil); + ~PluginLoader(); + + void send(uint16_t id, uint8_t length, const void* command); + + private: + bool __load(); + bool __load(const std::string& filePath); + void __unload(); + + AgentUtil& __agentUtil; + std::vector __plugins; + }; + +} + +#endif diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index b0c8ba2..0ec7782 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -26,7 +26,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_INSTALL_PREFIX}/${INCDIR}/private ) -FILE(GLOB_RECURSE SRCS *.cpp) +FILE(GLOB SRCS *.cpp ../shared/*.cpp) MESSAGE("Sources: ${SRCS}") INCLUDE(FindPkgConfig) diff --git a/src/server/ServerMain.cpp b/src/server/ServerMain.cpp index 312574d..ae62b7c 100644 --- a/src/server/ServerMain.cpp +++ b/src/server/ServerMain.cpp @@ -17,53 +17,18 @@ #include #include #include -#include -#include -#include #include #include +#include #include "DBusConnector.h" #include "ServiceLoader.h" #include "ActiveUserMonitor.h" #include "AlarmInitializer.h" -#define NEW_FAIL_LIMIT 3 - using namespace ctx; -namespace { - class MainLoop { - public: - static bool start(); - static void stop(); - private: - MainLoop() {} - static GMainLoop* __mainLoop; - }; -} - -GMainLoop* MainLoop::__mainLoop = NULL; - -bool MainLoop::start() -{ - __mainLoop = g_main_loop_new(NULL, FALSE); - IF_FAIL_RETURN_TAG(__mainLoop, false, _E, E_STR_ALLOC); - - _I(CYAN("Starting...")); - g_main_loop_run(__mainLoop); - - g_main_loop_unref(__mainLoop); - - return true; -} - -void MainLoop::stop() -{ - _I(PURPLE("Terminating...")); - g_main_loop_quit(__mainLoop); -} - +static MainLoop __mainLoop; static ServiceLoader __serviceLoader; static ActiveUserMonitor __activeUserMonitor(&__serviceLoader); static AlarmInitializer __alarmInit; @@ -89,7 +54,7 @@ static gboolean __stop_service(gpointer data) _I("Unloading services"); __serviceLoader.stopAll(); - MainLoop::stop(); + __mainLoop.stop(); return G_SOURCE_REMOVE; } @@ -114,43 +79,16 @@ static void __on_signal(int signum) } } -static void __on_terminate() -{ - try { - auto unknown = std::current_exception(); - if (unknown) { - std::rethrow_exception(unknown); - } - } catch (const std::exception& e) { - _E(RED("Unexpected exception: %s"), e.what()); - } catch (...) { - _E(RED("Unknown exception")); - } -} - -static void __on_new_failed() -{ - static unsigned failCount = 0; - _E_ALLOC; - failCount += 1; - if (failCount >= NEW_FAIL_LIMIT) - throw std::bad_alloc(); -} - int main(int argc, char* argv[]) { std::signal(SIGINT, __on_signal); std::signal(SIGHUP, __on_signal); std::signal(SIGTERM, __on_signal); std::signal(SIGQUIT, __on_signal); - std::signal(SIGABRT, __on_signal); - - std::set_terminate(__on_terminate); - std::set_new_handler(__on_new_failed); DBusConnector dbusConnector(__bus_acquired, __bus_lost); - MainLoop::start(); + __mainLoop.start(); return EXIT_SUCCESS; } diff --git a/src/shared/ServerBase.cpp b/src/shared/ServerBase.cpp new file mode 100644 index 0000000..2f60ced --- /dev/null +++ b/src/shared/ServerBase.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include +#include "ServerBase.h" + +#define NEW_FAIL_LIMIT 3 + +using namespace ctx; + +static void __on_terminate() +{ + try { + auto unknown = std::current_exception(); + if (unknown) { + std::rethrow_exception(unknown); + } + } catch (const std::exception& e) { + _E(RED("Unexpected exception: %s"), e.what()); + } catch (...) { + _E(RED("Unknown exception")); + } +} + +static void __on_new_failed() +{ + static unsigned failCount = 0; + _E_ALLOC; + failCount += 1; + if (failCount >= NEW_FAIL_LIMIT) + throw std::bad_alloc(); +} + +MainLoop::MainLoop() : + __mainLoop(NULL) +{ + std::set_terminate(__on_terminate); + std::set_new_handler(__on_new_failed); +} + +bool MainLoop::start() +{ + __mainLoop = g_main_loop_new(NULL, FALSE); + IF_FAIL_RETURN_TAG(__mainLoop, false, _E, E_STR_ALLOC); + + _I(CYAN("Starting...")); + g_main_loop_run(__mainLoop); + + g_main_loop_unref(__mainLoop); + __mainLoop = NULL; + + return true; +} + +void MainLoop::stop() +{ + if (__mainLoop && g_main_loop_is_running(__mainLoop)) { + _I(PURPLE("Terminating...")); + g_main_loop_quit(__mainLoop); + } +} diff --git a/src/shared/ServerBase.h b/src/shared/ServerBase.h new file mode 100644 index 0000000..e3bf1e4 --- /dev/null +++ b/src/shared/ServerBase.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CONEXT_SERVER_BASE_H__ +#define __CONEXT_SERVER_BASE_H__ + +#include + +namespace ctx { + class MainLoop { + public: + MainLoop(); + bool start(); + void stop(); + private: + GMainLoop* __mainLoop; + }; +} + +#endif -- 2.34.1