From aae388640a4fa6b772db232e28d6e4fc5a65278c Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 16 Oct 2014 18:35:48 +0200 Subject: [PATCH 01/16] Fix dlopened objects management * Add destroy function type, so deletion is compatible with allocation * Remove extern "C" from plugin creation/destruction typedefs * Add proper comments, so expected names of creation/destruction function symbol are known to API user Change-Id: I019f5bf83afc94945c8efc62e99dd324c419cc33 --- src/include/cynara-plugin.h | 17 +++++++++++++---- src/service/plugin/PluginManager.cpp | 18 ++++++++++++++++-- src/service/plugin/PluginManager.h | 3 ++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h index 83956fe..a9d6da7 100644 --- a/src/include/cynara-plugin.h +++ b/src/include/cynara-plugin.h @@ -34,11 +34,20 @@ namespace Cynara { class ExternalPluginInterface; -extern "C" { -typedef ExternalPluginInterface *(*createPlugin)(void); -} +/** + * Type of function used for creating objects implementing ExternalPluginInterface. + * Inside plugin library function with create_t signature should have symbol + * named "create". + */ +typedef ExternalPluginInterface *(*create_t)(void); +/** + * Type of function used for destroying objects created with "create". + * Inside plugin library function with destroy_t signature should have symbol + * named "destroy". + */ +typedef void (*destroy_t)(ExternalPluginInterface *); -//These typedefs will be defined in external headers +// These typedefs will be defined in external headers typedef std::string PluginData; typedef std::string AgentType; typedef std::vector PolicyTypes; diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp index 3d21b49..c591805 100644 --- a/src/service/plugin/PluginManager.cpp +++ b/src/service/plugin/PluginManager.cpp @@ -53,6 +53,14 @@ PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) { loadPlugins(); } +PluginManager::~PluginManager(void) { + // We have to be sure, that external objects will be destroyed + // before handles to libraries are closed. + for (auto &plugin : m_plugins) { + plugin.second.reset(); + } +} + ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) { return m_plugins[pType]; } @@ -90,7 +98,7 @@ void PluginManager::openPlugin(const std::string &path) { //Flush any previous errors dlerror(); - createPlugin func = reinterpret_cast(dlsym(handle, "create")); + create_t creator = reinterpret_cast(dlsym(handle, "create")); char *error; if ((error = dlerror()) != NULL) { @@ -98,7 +106,13 @@ void PluginManager::openPlugin(const std::string &path) { return; } - ExternalPluginPtr pluginPtr(func()); + destroy_t destroyer = reinterpret_cast(dlsym(handle, "destroy")); + if ((error = dlerror()) != NULL) { + LOGE("Couldn't resolve symbol from lib <%s> : <%s>", path.c_str(), error); + return; + } + + ExternalPluginPtr pluginPtr(creator(), destroyer); if (!pluginPtr) { LOGE("Couldn't create plugin for <%s>", path.c_str()); diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h index 6338cad..1abc6e6 100644 --- a/src/service/plugin/PluginManager.h +++ b/src/service/plugin/PluginManager.h @@ -23,6 +23,7 @@ #ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ #define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ +#include #include #include #include @@ -37,7 +38,7 @@ class PluginManager { public: PluginManager(const std::string &pluginDir); ExternalPluginPtr getPlugin(PolicyType pType); - ~PluginManager() {} + ~PluginManager(); private: typedef std::unique_ptr> PluginLibPtr; -- 2.7.4 From faf0647ea68e1114a28128b96598cdd4635bfb0c Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 16 Oct 2014 16:53:14 +0200 Subject: [PATCH 02/16] Add base class for external plugins * Make ExternalPluginInterface a base class providing only pure virtual getSupportedPolicyTypes() and publish its header * Change ExternalPluginInterface definition to ServicePluginInterface class and make it inherit after ExternalPluginInterface and publish its header as cynara-client-plugin.h * Rename InterpreterInterface to ClientServiceInterface, make it inherit after ExternalPluginInterface Change-Id: Ia572e2adb8a4486705f89903b31433d70d733381 --- packaging/cynara.spec | 2 + src/client-async/logic/Logic.cpp | 5 +- src/client-common/CMakeLists.txt | 1 + src/client-common/cache/CacheInterface.h | 6 +-- src/client-common/cache/CapacityCache.cpp | 2 +- src/client-common/plugins/NaiveInterpreter.cpp | 30 +++++++++++ src/client-common/plugins/NaiveInterpreter.h | 9 +++- src/client-common/plugins/PluginInterface.h | 48 ----------------- src/client/logic/Logic.cpp | 6 +-- src/common/CMakeLists.txt | 4 ++ src/common/plugin/ExternalPluginInterface.h | 60 +++++++++++++++++++++ src/include/CMakeLists.txt | 1 + src/include/cynara-client-plugin.h | 74 ++++++++++++++++++++++++++ src/include/cynara-plugin.h | 38 +++++-------- src/service/logic/Logic.cpp | 22 +++++--- src/service/plugin/PluginManager.cpp | 2 +- src/service/plugin/PluginManager.h | 2 +- 17 files changed, 220 insertions(+), 92 deletions(-) create mode 100644 src/client-common/plugins/NaiveInterpreter.cpp delete mode 100644 src/client-common/plugins/PluginInterface.h create mode 100644 src/common/plugin/ExternalPluginInterface.h create mode 100644 src/include/cynara-client-plugin.h diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 68d52ce..743f2a7 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -482,12 +482,14 @@ fi %files -n libcynara-commons-devel %{_includedir}/cynara/cynara-policy-types.h +%{_includedir}/cynara/plugin/ExternalPluginInterface.h %{_includedir}/cynara/types/PolicyResult.h %{_includedir}/cynara/types/PolicyType.h %{_libdir}/libcynara-commons.so %files -n libcynara-plugin-devel %{_includedir}/cynara/cynara-plugin.h +%{_includedir}/cynara/cynara-client-plugin.h %{_libdir}/pkgconfig/cynara-plugin.pc %files -n cynara-tests diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 921c2d6..bfb494c 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -49,8 +49,9 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter); + for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { + m_cache->registerPlugin(type, naiveInterpreter); + } } Logic::~Logic() { diff --git a/src/client-common/CMakeLists.txt b/src/client-common/CMakeLists.txt index 90e09d7..5436884 100644 --- a/src/client-common/CMakeLists.txt +++ b/src/client-common/CMakeLists.txt @@ -28,6 +28,7 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_COMMON_SOURCES ${LIB_CYNARA_COMMON_PATH}/cache/CapacityCache.cpp + ${LIB_CYNARA_COMMON_PATH}/plugins/NaiveInterpreter.cpp ) ADD_DEFINITIONS("-fvisibility=default") diff --git a/src/client-common/cache/CacheInterface.h b/src/client-common/cache/CacheInterface.h index 57455b8..03b7624 100644 --- a/src/client-common/cache/CacheInterface.h +++ b/src/client-common/cache/CacheInterface.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ public: const PolicyKey &key, const PolicyResult &result) = 0; - void registerPlugin(const PolicyType policyType, InterpreterInterfacePtr plugin) { + void registerPlugin(const PolicyType policyType, ClientPluginInterfacePtr plugin) { m_plugins[policyType] = plugin; } @@ -59,7 +59,7 @@ public: virtual ~PluginCache() {}; protected: - std::map m_plugins; + std::map m_plugins; }; } // namespace Cynara diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index d07bb2c..7eb7e34 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -55,7 +55,7 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { } //Is it still usable? - InterpreterInterfacePtr plugin = pluginIt->second; + ClientPluginInterfacePtr plugin = pluginIt->second; auto &prevSession = std::get<1>(cachedValue); auto usageIt = std::get<2>(cachedValue); bool updateSession = false; diff --git a/src/client-common/plugins/NaiveInterpreter.cpp b/src/client-common/plugins/NaiveInterpreter.cpp new file mode 100644 index 0000000..7141cb7 --- /dev/null +++ b/src/client-common/plugins/NaiveInterpreter.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/client-common/plugins/NaiveInterpreter.cpp + * @author Zofia Abramowska + * @version 1.0 + * @brief This file contains NaiveInterpreter supported types definition. + */ + +#include + +namespace Cynara { + + const std::vector NaiveInterpreter::s_supportedTypes = + {PredefinedPolicyType::ALLOW, PredefinedPolicyType::DENY}; + +} diff --git a/src/client-common/plugins/NaiveInterpreter.h b/src/client-common/plugins/NaiveInterpreter.h index e9e8ba4..8099362 100644 --- a/src/client-common/plugins/NaiveInterpreter.h +++ b/src/client-common/plugins/NaiveInterpreter.h @@ -28,7 +28,8 @@ namespace Cynara { -class NaiveInterpreter : public InterpreterInterface { +class NaiveInterpreter : public ClientPluginInterface { +public: bool isUsable(const ClientSession &session UNUSED, const ClientSession &prevSession UNUSED, bool &updateSession UNUSED, PolicyResult &result UNUSED) { return true; @@ -43,6 +44,12 @@ class NaiveInterpreter : public InterpreterInterface { else return CYNARA_API_ACCESS_DENIED; } + + const std::vector &getSupportedPolicyTypes(void) { + return s_supportedTypes; + } +private: + static const std::vector s_supportedTypes; }; } // namespace Cynara diff --git a/src/client-common/plugins/PluginInterface.h b/src/client-common/plugins/PluginInterface.h deleted file mode 100644 index 54bd341..0000000 --- a/src/client-common/plugins/PluginInterface.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2014 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 - */ -/** - * @file src/client-common/plugins/PluginInterface.h - * @author Zofia Abramowska - * @version 1.0 - * @brief This file contains plugin interface definitions. - */ - -#ifndef SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ -#define SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ - -#include - -#include -#include - -namespace Cynara { - -class InterpreterInterface; -typedef std::shared_ptr InterpreterInterfacePtr; - -class InterpreterInterface { -public: - virtual bool isCacheable(const ClientSession &session, const PolicyResult &result) = 0; - virtual bool isUsable(const ClientSession &session, const ClientSession &prevSession, - bool &updateSession, PolicyResult &result) = 0; - virtual int toResult(const ClientSession &session, PolicyResult &result) = 0; - - virtual ~InterpreterInterface() {}; -}; - -} // namespace Cynara - -#endif // SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index e05a168..498e53c 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -52,9 +52,9 @@ Logic::Logic() { std::make_shared()); m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::BUCKET, naiveInterpreter); + for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { + m_cache->registerPlugin(type, naiveInterpreter); + } } int Logic::check(const std::string &client, const ClientSession &session, const std::string &user, diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 61debfd..9dc48de 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -91,3 +91,7 @@ INSTALL(FILES ${COMMON_PATH}/types/PolicyType.h DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/types ) +INSTALL(FILES + ${COMMON_PATH}/plugin/ExternalPluginInterface.h + DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/plugin + ) diff --git a/src/common/plugin/ExternalPluginInterface.h b/src/common/plugin/ExternalPluginInterface.h new file mode 100644 index 0000000..bf3c7fe --- /dev/null +++ b/src/common/plugin/ExternalPluginInterface.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/plugin/ExternalPluginInterface.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines cynara side external plugin interface + */ + +#ifndef SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ +#define SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ + +#include + +#include + +namespace Cynara { + +class ExternalPluginInterface; + +/** + * Type of function used for creating objects implementing ExternalPluginInterface. + * Inside plugin library function with create_t signature should have symbol + * named "create". + */ +typedef ExternalPluginInterface *(*create_t)(void); + +/** + * Type of function used for destroying objects created with "create". + * Inside plugin library function with destroy_t signature should have symbol + * named "destroy". + */ +typedef void (*destroy_t)(ExternalPluginInterface *); + +class ExternalPluginInterface { +public: + + /** + * Policy type supported by plugin. + */ + virtual const std::vector &getSupportedPolicyTypes(void) = 0; + virtual ~ExternalPluginInterface() {} +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ */ diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index 1d672a8..b43bd1f 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin-types.h ${CYNARA_PATH}/include/cynara-client.h ${CYNARA_PATH}/include/cynara-client-async.h + ${CYNARA_PATH}/include/cynara-client-plugin.h ${CYNARA_PATH}/include/cynara-creds-commons.h ${CYNARA_PATH}/include/cynara-creds-dbus.h ${CYNARA_PATH}/include/cynara-creds-socket.h diff --git a/src/include/cynara-client-plugin.h b/src/include/cynara-client-plugin.h new file mode 100644 index 0000000..3d39ad7 --- /dev/null +++ b/src/include/cynara-client-plugin.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/include/cynara-client-plugin.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines cynara client side of external plugin interface - + * ClientPluginInterface. + */ + +#ifndef CYNARACLIENTPLUGIN_H_ +#define CYNARACLIENTPLUGIN_H_ + +#include + +#include +#include +#include + +namespace Cynara { + +class ClientPluginInterface; +typedef std::shared_ptr ClientPluginInterfacePtr; + +/** + * A class defining external plugins interface. + * These plugins work inside of cynara client library. They interpret + * PolicyResult returned by cynara in terms of: + * a) cacheability - tells, whether value should be cached (for e.g. policyType like + * ALLOW_ONCE should not be cached) + * b) usability - whether cache entry can still be used (for e.g. policy allowing access for + * given type) + * c) value - translates PolicyResult to CYNARA_API_ACCESS_ALLOWED or CYNARA_API_ACCESS_DENIED + * + * Plugin implementing ClientPluginInterface must implement ExternalPluginInterface. + * Creation/destruction functions with signatures compatible to Cynara::create_t and + * Cynara::destroy_t must be provided as factories of ClientPluginInterface. + */ +class ClientPluginInterface : public ExternalPluginInterface { +public: + + /** + * Return entry cacheability + */ + virtual bool isCacheable(const ClientSession &session, const PolicyResult &result) = 0; + /** + * Return entry cacheability + */ + virtual bool isUsable(const ClientSession &session, const ClientSession &prevSession, + bool &updateSession, PolicyResult &result) = 0; + /** + * Translate PolicyResult to CYNARA_API_ACCESS_ALLOWED or CYNARA_API_ACCESS_DENIED + */ + virtual int toResult(const ClientSession &session, PolicyResult &result) = 0; + + virtual ~ClientPluginInterface() {}; +}; + +} + +#endif // CYNARACLIENTPLUGIN_H_ diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h index a9d6da7..20e5e5c 100644 --- a/src/include/cynara-plugin.h +++ b/src/include/cynara-plugin.h @@ -17,7 +17,8 @@ * @file src/include/cynara-plugin.h * @author Zofia Abramowska * @version 1.0 - * @brief This file defines cynara side external plugin interface + * @brief This file defines cynara service side of external plugin interface - + * ServicePluginInterface */ #ifndef CYNARA_PLUGIN_H_ @@ -27,30 +28,18 @@ #include #include +#include #include #include namespace Cynara { -class ExternalPluginInterface; - -/** - * Type of function used for creating objects implementing ExternalPluginInterface. - * Inside plugin library function with create_t signature should have symbol - * named "create". - */ -typedef ExternalPluginInterface *(*create_t)(void); -/** - * Type of function used for destroying objects created with "create". - * Inside plugin library function with destroy_t signature should have symbol - * named "destroy". - */ -typedef void (*destroy_t)(ExternalPluginInterface *); - -// These typedefs will be defined in external headers +//These typedefs will be defined in external headers typedef std::string PluginData; typedef std::string AgentType; -typedef std::vector PolicyTypes; + +class ServicePluginInterface; +typedef std::shared_ptr ServicePluginInterfacePtr; /** * A class defining external plugins interface. @@ -58,9 +47,13 @@ typedef std::vector PolicyTypes; * response through check instantly or require communication * with given type of agent. Agent must be registered through * cynara-agent API. + * + * Plugin implementing ServicePluginInterface must implement ExternalPluginInterface. + * Creation/destruction functions with signatures compatible to Cynara::create_t and + * Cynara::destroy_t must be provided as factories of ServicePluginInterface. */ -class ExternalPluginInterface { +class ServicePluginInterface : public ExternalPluginInterface { public: /** * Enum indicating status of calling plugin method. @@ -74,11 +67,6 @@ public: }; /** - * Policy type supported by plugin. - */ - virtual PolicyTypes getSupportedPolicyTypes(void) = 0; - - /** * Asks plugin, what kind of permission does client, user and privilege has. * * @param[in] client @@ -107,7 +95,7 @@ public: const std::string &privilege, const PluginData &agentData, PolicyResult &result) noexcept = 0; - virtual ~ExternalPluginInterface() {}; + virtual ~ServicePluginInterface() {}; }; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index ca56d64..d4cc634 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -20,6 +20,8 @@ * @brief This file implements main class of logic layer in cynara service */ +#include + #include #include #include @@ -29,8 +31,9 @@ #include #include #include +#include -#include +#include #include
#include @@ -44,9 +47,8 @@ #include #include #include -#include - #include +#include #include "Logic.h" @@ -107,16 +109,22 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, throw PluginNotFoundException(result); } + ServicePluginInterfacePtr servicePlugin = + std::dynamic_pointer_cast(plugin); + if (!plugin) { + throw PluginNotFoundException(result); + } + AgentType requiredAgent; PluginData pluginData; - auto ret = plugin->check(key.client().toString(), key.user().toString(), - key.privilege().toString(), result, requiredAgent, pluginData); + auto ret = servicePlugin->check(key.client().toString(), key.user().toString(), + key.privilege().toString(), result, requiredAgent, pluginData); switch (ret) { - case ExternalPluginInterface::PluginStatus::ANSWER_READY: + case ServicePluginInterface::PluginStatus::ANSWER_READY: return true; - case ExternalPluginInterface::PluginStatus::ANSWER_NOTREADY: + case ServicePluginInterface::PluginStatus::ANSWER_NOTREADY: //todo send request to agent //context should be saved in plugin in order to return answer when ready return false; diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp index c591805..8062683 100644 --- a/src/service/plugin/PluginManager.cpp +++ b/src/service/plugin/PluginManager.cpp @@ -119,7 +119,7 @@ void PluginManager::openPlugin(const std::string &path) { return; } - PolicyTypes policies = pluginPtr->getSupportedPolicyTypes(); + auto policies = pluginPtr->getSupportedPolicyTypes(); if (policies.empty()) { LOGE("Plugin <%s> does not support any type!", path.c_str()); return; diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h index 1abc6e6..c2372e6 100644 --- a/src/service/plugin/PluginManager.h +++ b/src/service/plugin/PluginManager.h @@ -29,7 +29,7 @@ #include #include -#include +#include namespace Cynara { typedef std::shared_ptr ExternalPluginPtr; -- 2.7.4 From 0be98a2867acbe4e0e52c5b3211a5fd6ff071ab5 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 17 Oct 2014 18:28:34 +0200 Subject: [PATCH 03/16] Add PluginManager to CapacityCache Change-Id: Icdaf1df3793db0a43ae4aadcf2d8d306b04f650f --- src/client-common/cache/CapacityCache.cpp | 17 ++++++++++++----- src/client-common/cache/CapacityCache.h | 6 +++++- src/common/CMakeLists.txt | 1 + src/{service => common}/plugin/PluginManager.cpp | 0 src/{service => common}/plugin/PluginManager.h | 0 src/service/CMakeLists.txt | 1 - 6 files changed, 18 insertions(+), 7 deletions(-) rename src/{service => common}/plugin/PluginManager.cpp (100%) rename src/{service => common}/plugin/PluginManager.h (100%) diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index 7eb7e34..3174744 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -47,15 +47,22 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { auto &cachedValue = resultIt->second; auto &policyResult = std::get<0>(cachedValue); + ClientPluginInterfacePtr plugin; auto pluginIt = m_plugins.find(policyResult.policyType()); - if (pluginIt == m_plugins.end()) { - LOGE("No plugin registered for given PolicyType : %" PRIu16, - policyResult.policyType()); - return CYNARA_API_ACCESS_DENIED; + if (pluginIt != m_plugins.end()) { + plugin = pluginIt->second; + } else { + plugin = std::dynamic_pointer_cast( + m_pluginManager.getPlugin(policyResult.policyType())); + if (!plugin) { + LOGE("No plugin registered for given PolicyType : %" PRIu16, + policyResult.policyType()); + return CYNARA_API_ACCESS_DENIED; + } } //Is it still usable? - ClientPluginInterfacePtr plugin = pluginIt->second; + auto &prevSession = std::get<1>(cachedValue); auto usageIt = std::get<2>(cachedValue); bool updateSession = false; diff --git a/src/client-common/cache/CapacityCache.h b/src/client-common/cache/CapacityCache.h index 4218078..24e1092 100644 --- a/src/client-common/cache/CapacityCache.h +++ b/src/client-common/cache/CapacityCache.h @@ -29,6 +29,9 @@ #include +#include +#include + namespace Cynara { class CapacityCache : public PluginCache { @@ -36,7 +39,7 @@ public: static const std::size_t CACHE_DEFAULT_CAPACITY = 10000; CapacityCache(std::size_t capacity = CACHE_DEFAULT_CAPACITY) : - m_capacity(capacity) {} + m_capacity(capacity), m_pluginManager(PathConfig::PluginPath::clientDir) {} int get(const ClientSession &session, const PolicyKey &key); int update(const ClientSession& session, @@ -57,6 +60,7 @@ private: KeyUsageList m_keyUsage; KeyValueMap m_keyValue; + PluginManager m_pluginManager; }; } //namespace Cynara diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9dc48de..98f5133 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -29,6 +29,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/config/PathConfig.cpp ${COMMON_PATH}/containers/BinaryQueue.cpp ${COMMON_PATH}/log/log.cpp + ${COMMON_PATH}/plugin/PluginManager.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp ${COMMON_PATH}/protocol/ProtocolClient.cpp ${COMMON_PATH}/protocol/ProtocolFrame.cpp diff --git a/src/service/plugin/PluginManager.cpp b/src/common/plugin/PluginManager.cpp similarity index 100% rename from src/service/plugin/PluginManager.cpp rename to src/common/plugin/PluginManager.cpp diff --git a/src/service/plugin/PluginManager.h b/src/common/plugin/PluginManager.h similarity index 100% rename from src/service/plugin/PluginManager.h rename to src/common/plugin/PluginManager.h diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index f8d2eb8..c317d8e 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -22,7 +22,6 @@ SET(CYNARA_SOURCES ${CYNARA_SERVICE_PATH}/logic/Logic.cpp ${CYNARA_SERVICE_PATH}/main/Cynara.cpp ${CYNARA_SERVICE_PATH}/main/main.cpp - ${CYNARA_SERVICE_PATH}/plugin/PluginManager.cpp ${CYNARA_SERVICE_PATH}/sockets/Descriptor.cpp ${CYNARA_SERVICE_PATH}/sockets/SocketManager.cpp ) -- 2.7.4 From 73bee30c040050883a812bdbf2e02ad4cd54f776 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Mon, 15 Sep 2014 14:47:22 +0200 Subject: [PATCH 04/16] Add agent socket & dummy agent protocol This change introduces new systemd based socket and protocol for communication with agents. Protocol does not contain any agent specific frame information for now. Change-Id: I83e2211a25fd93792a46a64c1df519efb1cedfed --- packaging/cynara.spec | 3 ++ src/common/CMakeLists.txt | 1 + src/common/common.h | 1 - src/common/config/PathConfig.cpp | 1 + src/common/config/PathConfig.h | 1 + src/common/protocol/ProtocolAgent.cpp | 84 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAgent.h | 47 ++++++++++++++++++++ src/service/sockets/SocketManager.cpp | 4 ++ systemd/CMakeLists.txt | 1 + systemd/cynara-agent.socket | 14 ++++++ systemd/cynara.service | 1 + 11 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/common/protocol/ProtocolAgent.cpp create mode 100644 src/common/protocol/ProtocolAgent.h create mode 100644 systemd/cynara-agent.socket diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 743f2a7..8a3e298 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -287,6 +287,7 @@ mkdir -p %{buildroot}/%{tests_dir}/empty_db cp -a db* %{buildroot}/%{tests_dir} ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket +ln -s ../cynara-agent.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-agent.socket %pre id -g %{group_name} > /dev/null 2>&1 @@ -425,6 +426,8 @@ fi %attr(-,root,root) /usr/lib/systemd/system/cynara.socket %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket %attr(-,root,root) /usr/lib/systemd/system/cynara-admin.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/cynara-agent.socket +%attr(-,root,root) /usr/lib/systemd/system/cynara-agent.socket %dir %attr(700,cynara,cynara) %{state_path} %files -n libcynara-client diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 98f5133..72b7d7f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -31,6 +31,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/log/log.cpp ${COMMON_PATH}/plugin/PluginManager.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp + ${COMMON_PATH}/protocol/ProtocolAgent.cpp ${COMMON_PATH}/protocol/ProtocolClient.cpp ${COMMON_PATH}/protocol/ProtocolFrame.cpp ${COMMON_PATH}/protocol/ProtocolFrameHeader.cpp diff --git a/src/common/common.h b/src/common/common.h index 5d93cdc..95ff89c 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -32,5 +32,4 @@ #include "types/PolicyTypeExtension.h" - #endif /* COMMON_H */ diff --git a/src/common/config/PathConfig.cpp b/src/common/config/PathConfig.cpp index a5a603b..f2799a1 100644 --- a/src/common/config/PathConfig.cpp +++ b/src/common/config/PathConfig.cpp @@ -47,6 +47,7 @@ const std::string clientPath("/run/cynara/"); namespace SocketPath { const std::string client(clientPath + "cynara.socket"); const std::string admin(clientPath + "cynara-admin.socket"); +const std::string agent(clientPath + "cynara-agent.socket"); } // namespace SocketPath namespace StoragePath { diff --git a/src/common/config/PathConfig.h b/src/common/config/PathConfig.h index 27b10c2..2f5836a 100644 --- a/src/common/config/PathConfig.h +++ b/src/common/config/PathConfig.h @@ -35,6 +35,7 @@ extern const std::string clientPath; namespace SocketPath { extern const std::string client; extern const std::string admin; +extern const std::string agent; } // namespace SocketPath namespace StoragePath { diff --git a/src/common/protocol/ProtocolAgent.cpp b/src/common/protocol/ProtocolAgent.cpp new file mode 100644 index 0000000..f4d26a1 --- /dev/null +++ b/src/common/protocol/ProtocolAgent.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/protocol/ProtocolAgent.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements protocol class for communication with agent + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ProtocolAgent.h" + +namespace Cynara { + +ProtocolAgent::ProtocolAgent() { +} + +ProtocolAgent::~ProtocolAgent() { +} + +ProtocolPtr ProtocolAgent::clone(void) { + return std::make_shared(); +} + +RequestPtr ProtocolAgent::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); + switch (opCode) { + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +ResponsePtr ProtocolAgent::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); + switch (opCode) { + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +} // namespace Cynara diff --git a/src/common/protocol/ProtocolAgent.h b/src/common/protocol/ProtocolAgent.h new file mode 100644 index 0000000..68baf46 --- /dev/null +++ b/src/common/protocol/ProtocolAgent.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/protocol/ProtocolAgent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines protocol class for communication with agent + */ + +#ifndef SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ +#define SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ + +#include +#include +#include + +#include "Protocol.h" + +namespace Cynara { + +class ProtocolAgent : public Protocol { +public: + ProtocolAgent(); + virtual ~ProtocolAgent(); + + virtual ProtocolPtr clone(void); + + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ */ diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index 3161dc7..e454271 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -45,6 +45,7 @@ #include #include
#include +#include #include #include #include @@ -72,11 +73,14 @@ void SocketManager::init(void) { LOGI("SocketManger init start"); const mode_t clientSocketUMask(0); const mode_t adminSocketUMask(0077); + const mode_t agentSocketUMask(0); createDomainSocket(std::make_shared(), PathConfig::SocketPath::client, clientSocketUMask, true); createDomainSocket(std::make_shared(), PathConfig::SocketPath::admin, adminSocketUMask, false); + createDomainSocket(std::make_shared(), PathConfig::SocketPath::agent, + agentSocketUMask, false); createSignalSocket(std::make_shared()); LOGI("SocketManger init done"); } diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index 8fc27e7..a540263 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/cynara.target ${CMAKE_SOURCE_DIR}/systemd/cynara.socket ${CMAKE_SOURCE_DIR}/systemd/cynara-admin.socket + ${CMAKE_SOURCE_DIR}/systemd/cynara-agent.socket DESTINATION lib/systemd/system ) diff --git a/systemd/cynara-agent.socket b/systemd/cynara-agent.socket new file mode 100644 index 0000000..96fc54a --- /dev/null +++ b/systemd/cynara-agent.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/cynara/cynara-agent.socket +SocketMode=0060 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=cynara.service + +[Unit] +Wants=cynara.target +Before=cynara.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/cynara.service b/systemd/cynara.service index 847a294..99176fa 100644 --- a/systemd/cynara.service +++ b/systemd/cynara.service @@ -12,6 +12,7 @@ Restart=always Sockets=cynara.socket Sockets=cynara-admin.socket +Sockets=cynara-agent.socket UMask=0000 User=cynara -- 2.7.4 From 03998323f9b30dd11cd920bbc0531029dbf0c063 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 23 Sep 2014 13:52:19 +0200 Subject: [PATCH 05/16] Add agent API This patch introduces API for agents cooperating with plugins. Agents communicate with plugins via cynara service. Change-Id: I0f6233838f27370ee980655ad09be9fd10ae1bce --- src/include/cynara-agent.h | 213 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/include/cynara-agent.h diff --git a/src/include/cynara-agent.h b/src/include/cynara-agent.h new file mode 100644 index 0000000..43026cb --- /dev/null +++ b/src/include/cynara-agent.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/include/cynara-agent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains agent APIs available with libcynara-agent. + */ + +#ifndef CYNARA_AGENT_H +#define CYNARA_AGENT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint16_t cynara_agent_req_id; +typedef struct cynara_agent cynara_agent; + +/** + * \enum cynara_agent_msg_type + * Values specifying type of message. + * + * \var cynara_agent_msg_type::CYNARA_MSG_TYPE_ACTION + * Message of this type indicates its content is a request for performing an action or response to + * such request. + * + * \var cynara_agent_msg_type::CYNARA_MSG_TYPE_CANCEL + * Message of this type indicates its content is a request for canceling action or response to such + * request. + */ +typedef enum { + CYNARA_MSG_TYPE_ACTION, + CYNARA_MSG_TYPE_CANCEL +} cynara_agent_msg_type; + +/** + * \par Description: + * Initialize cynara-agent library. + * Create structure used in following API calls. + * + * \par Purpose: + * This API must be used prior to calling other agent API functions. + * + * \par Typical use case: + * Once before other agent API functions are called. + * + * \par Method of function operation: + * This API initializes inner library structures and in case of success returns cynara_agent + * structure. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Structure cynara_agent created by this function should be released with cynara_agent_finish. + * + * \param[out] pp_cynara_agent Place holder for created cynara_agent structure. + * \param[in] p_agent_type Type (name) of agent used by cynara for communication agent<->plugin. + * + * \return CYNARA_API_SUCCESS on success, or error code on error. + */ +int cynara_agent_initialize(cynara_agent **pp_cynara_agent, const char *p_agent_type); + +/** + * \par Description: + * Release cynara-agent library and destroy structure created with cynara_agent_initialize(). + * + * \par Purpose: + * This API should be used to clean up after usage of cynara-agent library. + * + * \par Typical use case: + * Once after connection to cynara is not needed. + * + * \par Method of function operation: + * This API releases inner library structure and destroys cynara_agent structure. Connection to + * cynara service is closed. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread-safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * No other call to cynara-agent library should be made after call to cynara_agent_finish() except + * cynara_agent_initialize(). + * + * \param[in] p_cynara_agent cynara_agent structure. If NULL, then the call has no effect. + */ +int cynara_agent_finish(cynara_agent *p_cynara_agent); + +/** + * \par Description: + * Get request from cynara service. + * + * \par Purpose: + * This API should be used to get request from cynara service. Request is generated by corresponding + * plugin loaded into cynara service. + * + * \par Typical use case: + * Agent waits for request from cynara service. Request may be either ask for performing agent + * specific action or ask for canceling such action. Agent calls this function when is ready to + * perform or cancel an action. + * + * \par Method of function operation: + * Function reads data incoming from cynara service and if at least one complete request is ready + * then returns with CYNARA_API_SUCCESS code. Request type, request id and specific + * plugin data are stored in given arguments. Function returns exactly one request. If there are + * more then one requests ready to get then one must call this function multiple times. + * This function is blocking which means that if there is no request from cynara service it will not + * return. On success, buffer for plugin specific data is allocated and size is set. Developer is + * responsible for freeing this memory using free() function. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Call to cynara_agent_get_request() needs cynara_agent structure to be created first. + * Use cynara_agent_initialize() before calling this function. + * After CYNARA_API_ACCESS_DENIED error is returned agent should be terminated or at least should + * not invoke neither cynara_agent_get_request() nor cynara_agent_put_response() functions. + * + * \param[in] p_cynara_agent cynara_agent structure. + * \param[out] req_type Request type, demand an action or cancel this action. + * \param[out] req_id Request identifier used to pair with answer #cynara_agent_put_response() and + * cancel request. + * \param[out] data Plugin specific data. Buffer is allocated in this function and developer is + * responsible for freeing it using free() function. Buffer is filled with data + * from corresponding plugin. If there is no enough memory for data + * CYNARA_API_OUT_OF_MEMORY is returned and all arguments remain untouched. + * \param[out] data_size Size of plugin data (bytes count). In case of out of memory this value + * stays untouched. + * + * \return CYNARA_API_SUCCESS on successfully read request, or negative error code otherwise. + */ +int cynara_agent_get_request(cynara_agent *p_cynara_agent, cynara_agent_msg_type *req_type, + cynara_agent_req_id *req_id, void **data, size_t *data_size); + +/** + * \par Description: + * Send response to cynara service. + * + * \par Purpose: + * This API should be used to send response to cynara service. + * + * \par Typical use case: + * Agent calls this function when is ready to answer request for action or cancel request. + * + * \par Method of function operation: + * Function sends data to cynara service. Data contains answer for previously got question. + * Answer may be of type CYNARA_MSG_TYPE_ACTION or CYNARA_MSG_TYPE_CANCEL. Type is + * CYNARA_MSG_TYPE_ACTION when request for an action was processed and answer is ready, or + * CYNARA_MSG_TYPE_CANCEL when processing request for an action was interrupted by cancel request. + * Agent must send exactly one response per one request and cancel. If request is processed before + * cancel message arrives the agent sends action response. If cancel arrives before action request + * is processed then agent sends cancel response and drops processing related action. + * Request id in response must be the same as request id in corresponding request. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Call to cynara_agent_get_request() needs cynara_agent structure to be created first. + * Use cynara_agent_initialize() before calling this function. Also successful call to + * cynara_agent_get_request() is needed before calling this function. + * + * \param[in] p_cynara_agent cynara_agent structure. + * \param[in] resp_type Response type - see Method of operation for details. + * \param[in] req_id Request identifier obtained from request. + * \param[in] data Plugin specific data. If necessary agent should fill this buffer with data + * directed to plugin. + * \param[in] data_size Size of plugin data (bytes count). + * + * \return CYNARA_API_SUCCESS on successfully read request, or negative error code otherwise. + */ +int cynara_agent_put_response(cynara_agent *p_cynara_agent, const cynara_agent_msg_type resp_type, + const cynara_agent_req_id req_id, const void *data, + const size_t data_size); + +#ifdef __cplusplus +} +#endif + +#endif /* CYNARA_AGENT_H */ -- 2.7.4 From f242b4ad2e55d02d869e0a7b7cff508796ac4119 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 2 Oct 2014 14:06:45 +0200 Subject: [PATCH 06/16] Add agent library stub implementation This patch introduces implementation of agent library. Connection to cynara service is not yet implemented. Only basic structure of library is created. Change-Id: Iff771cbff35c1eb4f0c3842631f2fd65ea322ee8 --- CMakeLists.txt | 1 + packaging/cynara.spec | 57 ++++++++++--- packaging/libcynara-agent.manifest | 5 ++ pkgconfig/CMakeLists.txt | 1 + pkgconfig/cynara-agent/CMakeLists.txt | 25 ++++++ pkgconfig/cynara-agent/cynara-agent.pc.in | 11 +++ src/CMakeLists.txt | 1 + src/agent/CMakeLists.txt | 47 +++++++++++ src/agent/api/ApiInterface.h | 47 +++++++++++ src/agent/api/agent-api.cpp | 125 ++++++++++++++++++++++++++++ src/agent/logic/Logic.cpp | 47 +++++++++++ src/agent/logic/Logic.h | 49 +++++++++++ src/common/CMakeLists.txt | 1 + src/common/request/pointers.h | 3 + src/common/response/AgentActionResponse.cpp | 36 ++++++++ src/common/response/AgentActionResponse.h | 59 +++++++++++++ src/common/response/ResponseTaker.cpp | 4 + src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 + src/common/types/Agent.h | 37 ++++++++ src/include/CMakeLists.txt | 1 + 21 files changed, 550 insertions(+), 11 deletions(-) create mode 100644 packaging/libcynara-agent.manifest create mode 100644 pkgconfig/cynara-agent/CMakeLists.txt create mode 100644 pkgconfig/cynara-agent/cynara-agent.pc.in create mode 100644 src/agent/CMakeLists.txt create mode 100644 src/agent/api/ApiInterface.h create mode 100644 src/agent/api/agent-api.cpp create mode 100644 src/agent/logic/Logic.cpp create mode 100644 src/agent/logic/Logic.h create mode 100644 src/common/response/AgentActionResponse.cpp create mode 100644 src/common/response/AgentActionResponse.h create mode 100644 src/common/types/Agent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c72d22..dc951bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ SET(TARGET_LIB_CYNARA "cynara-client") SET(TARGET_LIB_CYNARA_ASYNC "cynara-client-async") SET(TARGET_LIB_CYNARA_COMMON "cynara-client-commons") SET(TARGET_LIB_CYNARA_ADMIN "cynara-admin") +SET(TARGET_LIB_CYNARA_AGENT "cynara-agent") SET(TARGET_CYNARA_COMMON "cynara-commons") SET(TARGET_CYNARA_TESTS "cynara-tests") SET(TARGET_LIB_CREDS_COMMONS "cynara-creds-commons") diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 8a3e298..88e9209 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -11,14 +11,15 @@ Source1002: libcynara-client.manifest Source1003: libcynara-client-async.manifest Source1004: libcynara-admin.manifest Source1005: cynara-tests.manifest -Source1006: libcynara-client-commons.manifest -Source1007: libcynara-commons.manifest -Source1008: libcynara-creds-commons.manifest -Source1009: libcynara-creds-dbus.manifest -Source1010: libcynara-creds-socket.manifest -Source1011: libcynara-session.manifest -Source1012: libcynara-storage.manifest -Source1013: cynara-db-migration.manifest +Source1006: libcynara-agent.manifest +Source1007: libcynara-client-commons.manifest +Source1008: libcynara-commons.manifest +Source1009: libcynara-creds-commons.manifest +Source1010: libcynara-creds-dbus.manifest +Source1011: libcynara-creds-socket.manifest +Source1012: libcynara-session.manifest +Source1013: libcynara-storage.manifest +Source1014: cynara-db-migration.manifest Requires: default-ac-domains Requires(pre): pwdutils Requires(pre): cynara-db-migration >= %{version}-%{release} @@ -51,9 +52,8 @@ BuildRequires: pkgconfig(libunwind) %description service, client libraries (libcynara-client, libcynara-client-async, libcynara-admin), -helper libraries (libcynara-session, libcynara-creds-common, libcynara-creds-dbus, -libcynara-creds-socket) -and tests (cynara-tests) +agent library, helper libraries (libcynara-session, libcynara-creds-common, libcynara-creds-dbus, +libcynara-creds-socket) and tests (cynara-tests) ####################################################### %package -n libcynara-client @@ -118,6 +118,22 @@ Requires: libcynara-commons-devel = %{version}-%{release} admin client library (devel) for setting, listing and removing policies ####################################################### +%package -n libcynara-agent +Summary: Cynara - agent client library +Requires: cynara = %{version}-%{release} + +%description -n libcynara-agent +agent client library for communication with cynara service and plugins + +%package -n libcynara-agent-devel +Summary: Cynara - agent client library (devel) +Requires: libcynara-agent = %{version}-%{release} +Requires: libcynara-client-commons-devel = %{version}-%{release} + +%description -n libcynara-agent-devel +agent client library (devel) for communication with cynara service and plugins + +####################################################### %package -n libcynara-storage Summary: Cynara - storage @@ -252,6 +268,7 @@ cp -a %{SOURCE1010} . cp -a %{SOURCE1011} . cp -a %{SOURCE1012} . cp -a %{SOURCE1013} . +cp -a %{SOURCE1014} . cp -a test/db/db* . %build @@ -352,6 +369,10 @@ fi %postun -n libcynara-admin -p /sbin/ldconfig +%post -n libcynara-agent -p /sbin/ldconfig + +%postun -n libcynara-agent -p /sbin/ldconfig + %post -n libcynara-storage -p /sbin/ldconfig %postun -n libcynara-storage -p /sbin/ldconfig @@ -380,6 +401,10 @@ fi %postun -n libcynara-admin-devel -p /sbin/ldconfig +%post -n libcynara-agent-devel -p /sbin/ldconfig + +%postun -n libcynara-agent-devel -p /sbin/ldconfig + %post -n libcynara-commons-devel -p /sbin/ldconfig %postun -n libcynara-commons-devel -p /sbin/ldconfig @@ -470,6 +495,16 @@ fi %{_libdir}/libcynara-admin.so %{_libdir}/pkgconfig/cynara-admin.pc +%files -n libcynara-agent +%manifest libcynara-agent.manifest +%license LICENSE +%{_libdir}/libcynara-agent.so.* + +%files -n libcynara-agent-devel +%{_includedir}/cynara/cynara-agent.h +%{_libdir}/libcynara-agent.so +%{_libdir}/pkgconfig/cynara-agent.pc + %files -n libcynara-storage %manifest libcynara-storage.manifest %license LICENSE diff --git a/packaging/libcynara-agent.manifest b/packaging/libcynara-agent.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libcynara-agent.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index a93ae55..e37f19a 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -20,6 +20,7 @@ ADD_SUBDIRECTORY(cynara-client) ADD_SUBDIRECTORY(cynara-client-async) ADD_SUBDIRECTORY(cynara-admin) +ADD_SUBDIRECTORY(cynara-agent) ADD_SUBDIRECTORY(cynara-creds-commons) ADD_SUBDIRECTORY(cynara-creds-dbus) ADD_SUBDIRECTORY(cynara-creds-socket) diff --git a/pkgconfig/cynara-agent/CMakeLists.txt b/pkgconfig/cynara-agent/CMakeLists.txt new file mode 100644 index 0000000..7782e29 --- /dev/null +++ b/pkgconfig/cynara-agent/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2014 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. +# +# @file pkgconfig/cynara-agent/CMakeLists.txt +# @author Adam Malinowski +# + +CONFIGURE_FILE(cynara-agent.pc.in cynara-agent.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-agent/cynara-agent.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig + ) diff --git a/pkgconfig/cynara-agent/cynara-agent.pc.in b/pkgconfig/cynara-agent/cynara-agent.pc.in new file mode 100644 index 0000000..363a75c --- /dev/null +++ b/pkgconfig/cynara-agent/cynara-agent.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: cynara-agent +Description: cynara-agent package +Version: @CYNARA_VERSION@ +Requires: +Libs: -L${libdir} -lcynara-agent +Cflags: -I${includedir}/cynara diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe4d096..60a8a40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,6 +49,7 @@ ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(client-async) ADD_SUBDIRECTORY(client-common) ADD_SUBDIRECTORY(admin) +ADD_SUBDIRECTORY(agent) ADD_SUBDIRECTORY(storage) ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(helpers/creds-commons) diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt new file mode 100644 index 0000000..1f31692 --- /dev/null +++ b/src/agent/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (c) 2014 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. +# +# @file src/agent/CMakeLists.txt +# @author Adam Malinowski +# + +SET(LIB_CYNARA_AGENT_VERSION_MAJOR 0) +SET(LIB_CYNARA_AGENT_VERSION ${LIB_CYNARA_AGENT_VERSION_MAJOR}.3.0) + +SET(CYNARA_LIB_CYNARA_AGENT_PATH ${CYNARA_PATH}/agent) + +SET(LIB_CYNARA_AGENT_SOURCES + ${CYNARA_LIB_CYNARA_AGENT_PATH}/api/agent-api.cpp + ${CYNARA_LIB_CYNARA_AGENT_PATH}/logic/Logic.cpp + ) + +INCLUDE_DIRECTORIES( + ${CYNARA_PATH}/include + ${CYNARA_LIB_CYNARA_AGENT_PATH} + ) + +ADD_LIBRARY(${TARGET_LIB_CYNARA_AGENT} SHARED ${LIB_CYNARA_AGENT_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_LIB_CYNARA_AGENT} + PROPERTIES + SOVERSION ${LIB_CYNARA_AGENT_VERSION_MAJOR} + VERSION ${LIB_CYNARA_AGENT_VERSION} + ) + +TARGET_LINK_LIBRARIES(${TARGET_LIB_CYNARA_AGENT} + ${TARGET_CYNARA_COMMON} + ) + +INSTALL(TARGETS ${TARGET_LIB_CYNARA_AGENT} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/agent/api/ApiInterface.h b/src/agent/api/ApiInterface.h new file mode 100644 index 0000000..93c5245 --- /dev/null +++ b/src/agent/api/ApiInterface.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/api/ApiInterface.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains libcynara-agent API interface definition. + */ + +#ifndef SRC_AGENT_API_APIINTERFACE_H_ +#define SRC_AGENT_API_APIINTERFACE_H_ + +#include +#include +#include +#include + +namespace Cynara { + +class ApiInterface { +public: + ApiInterface() = default; + virtual ~ApiInterface() {}; + + virtual int getRequest(AgentActionResponsePtr &actionResponsePtr) = 0; + + virtual int putResponse(AgentRequestType requestType, + ProtocolFrameSequenceNumber sequenceNumber, + const RawBuffer &pluginData) = 0; +}; + +} // namespace Cynara + +#endif /* SRC_AGENT_API_APIINTERFACE_H_ */ diff --git a/src/agent/api/agent-api.cpp b/src/agent/api/agent-api.cpp new file mode 100644 index 0000000..4baec2d --- /dev/null +++ b/src/agent/api/agent-api.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/api/agent-api.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief Implementation of external libcynara-agent API + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct cynara_agent { + Cynara::ApiInterface *impl; + + cynara_agent(Cynara::ApiInterface *_impl) : impl(_impl) {} + + ~cynara_agent() { + delete impl; + } +}; + +CYNARA_API +int cynara_agent_initialize(cynara_agent **pp_cynara_agent, const char *p_agent_type) { + if (!pp_cynara_agent) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + *pp_cynara_agent = new cynara_agent(new Cynara::Logic(p_agent_type)); + + init_log(); + + LOGD("Cynara agent initialized"); + + return CYNARA_API_SUCCESS; + }); +} + +CYNARA_API +int cynara_agent_finish(cynara_agent *pp_cynara_agent) { + delete pp_cynara_agent; + + return CYNARA_API_SUCCESS; +} + +CYNARA_API +int cynara_agent_get_request(cynara_agent *p_cynara_agent, cynara_agent_msg_type *req_type, + cynara_agent_req_id *req_id, void **data, size_t *data_size) { + + if (!p_cynara_agent || !p_cynara_agent->impl) + return CYNARA_API_INVALID_PARAM; + if (!req_type || !req_id) + return CYNARA_API_INVALID_PARAM; + if (!data || !data_size) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + Cynara::AgentActionResponsePtr actionResponsePtr; + int ret = p_cynara_agent->impl->getRequest(actionResponsePtr); + if (ret != CYNARA_API_SUCCESS) + return ret; + + size_t dataSize = actionResponsePtr->data().size(); + if (dataSize > 0) { + void *tmpData = malloc(dataSize); + if (tmpData == nullptr) + return CYNARA_API_OUT_OF_MEMORY; + + *data = tmpData; + memcpy(*data, actionResponsePtr->data().data(), dataSize); + } + + *data_size = dataSize; + *req_type = static_cast(actionResponsePtr->type()); + *req_id = actionResponsePtr->sequenceNumber(); + + return CYNARA_API_SUCCESS; + }); +} + +CYNARA_API +int cynara_agent_put_response(cynara_agent *p_cynara_agent, const cynara_agent_msg_type resp_type, + const cynara_agent_req_id req_id, const void *data, + const size_t data_size) { + + if (!p_cynara_agent || !p_cynara_agent->impl) + return CYNARA_API_INVALID_PARAM; + if ((resp_type != CYNARA_MSG_TYPE_ACTION) && (resp_type != CYNARA_MSG_TYPE_CANCEL)) + return CYNARA_API_INVALID_PARAM; + if ((!data && data_size) || (data && !data_size)) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + const char *first = static_cast(data); + const char *last = first + data_size; + Cynara::RawBuffer pluginData(first, last); + return p_cynara_agent->impl->putResponse(resp_type, req_id, pluginData); + }); +} diff --git a/src/agent/logic/Logic.cpp b/src/agent/logic/Logic.cpp new file mode 100644 index 0000000..b8a66d4 --- /dev/null +++ b/src/agent/logic/Logic.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/logic/Logic.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains implementation of Logic class - main libcynara-agent class + */ + +#include + +#include + +#include "Logic.h" + +namespace Cynara { + +Logic::Logic(const AgentType &agentType) : m_agentType(agentType) { +} + +int Logic::getRequest(AgentActionResponsePtr &resultPtr UNUSED) { + // TODO: implement + return CYNARA_API_SUCCESS; +} + +int Logic::putResponse(const AgentResponseType responseType UNUSED, + const ProtocolFrameSequenceNumber sequenceNumber UNUSED, + const RawBuffer &pluginData UNUSED) { + + // TODO: implement + return CYNARA_API_SUCCESS; +} + +} // namespace Cynara diff --git a/src/agent/logic/Logic.h b/src/agent/logic/Logic.h new file mode 100644 index 0000000..facead7 --- /dev/null +++ b/src/agent/logic/Logic.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/logic/Logic.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains definition of Logic class - main libcynara-agent class + */ + +#ifndef SRC_AGENT_LOGIC_LOGIC_H_ +#define SRC_AGENT_LOGIC_LOGIC_H_ + +#include + +#include + +namespace Cynara { + +class Logic : public ApiInterface { +public: + Logic(const AgentType &agentType); + virtual ~Logic() {}; + + virtual int getRequest(AgentActionResponsePtr &actionResponsePtr); + + virtual int putResponse(const AgentResponseType responseType, + const ProtocolFrameSequenceNumber sequenceNumber, + const RawBuffer &pluginData); + +private: + AgentType m_agentType; +}; + +} // namespace Cynara + +#endif /* SRC_AGENT_LOGIC_LOGIC_H_ */ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 72b7d7f..42f66eb 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -46,6 +46,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/RequestTaker.cpp ${COMMON_PATH}/request/SetPoliciesRequest.cpp ${COMMON_PATH}/request/SignalRequest.cpp + ${COMMON_PATH}/response/AgentActionResponse.cpp ${COMMON_PATH}/response/CancelResponse.cpp ${COMMON_PATH}/response/CheckResponse.cpp ${COMMON_PATH}/response/CodeResponse.cpp diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index 5c90004..e20a6ad 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -30,6 +30,9 @@ namespace Cynara { class AdminCheckRequest; typedef std::shared_ptr AdminCheckRequestPtr; +class AgentActionRequest; +typedef std::shared_ptr AgentActionRequestPtr; + class CancelRequest; typedef std::shared_ptr CancelRequestPtr; diff --git a/src/common/response/AgentActionResponse.cpp b/src/common/response/AgentActionResponse.cpp new file mode 100644 index 0000000..4a8bcc8 --- /dev/null +++ b/src/common/response/AgentActionResponse.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/response/AgentActionResponse.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements common class for sending a request to agent + */ + +#include + +#include + +#include "AgentActionResponse.h" + +namespace Cynara { + +void AgentActionResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/AgentActionResponse.h b/src/common/response/AgentActionResponse.h new file mode 100644 index 0000000..f99c043 --- /dev/null +++ b/src/common/response/AgentActionResponse.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/response/AgentActionResponse.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines class for responding to agent action request + */ + +#ifndef SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ +#define SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ + +#include +#include +#include +#include +#include + +namespace Cynara { + +class AgentActionResponse : public Response { +public: + AgentActionResponse(const AgentResponseType type, const RawBuffer &data, + ProtocolFrameSequenceNumber sequenceNumber) : Response(sequenceNumber), + m_type(type), m_data(data) {} + + ~AgentActionResponse() {} + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, RequestContextPtr context) const; + + const RawBuffer &data(void) const { + return m_data; + } + + AgentResponseType type(void) const { + return m_type; + } + +private: + const AgentResponseType m_type; + const RawBuffer m_data; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index 3f558c4..34f84f5 100644 --- a/src/common/response/ResponseTaker.cpp +++ b/src/common/response/ResponseTaker.cpp @@ -28,6 +28,10 @@ namespace Cynara { +void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentActionResponsePtr response UNUSED) { + throw NotImplementedException(); +} + void ResponseTaker::execute(RequestContextPtr context UNUSED, CancelResponsePtr response UNUSED) { throw NotImplementedException(); } diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 0afdb65..1642072 100644 --- a/src/common/response/ResponseTaker.h +++ b/src/common/response/ResponseTaker.h @@ -33,6 +33,7 @@ public: ResponseTaker() = default; virtual ~ResponseTaker() {}; + virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); virtual void execute(RequestContextPtr context, CancelResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); diff --git a/src/common/response/pointers.h b/src/common/response/pointers.h index 4e9b8fc..1774a4b 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class AgentActionResponse; +typedef std::shared_ptr AgentActionResponsePtr; + class CancelResponse; typedef std::shared_ptr CancelResponsePtr; diff --git a/src/common/types/Agent.h b/src/common/types/Agent.h new file mode 100644 index 0000000..7f26af7 --- /dev/null +++ b/src/common/types/Agent.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/types/Agent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines agent related types + */ + +#ifndef SRC_COMMON_TYPES_AGENT_H_ +#define SRC_COMMON_TYPES_AGENT_H_ + +#include +#include + +namespace Cynara { + +typedef std::uint8_t AgentRequestType; +typedef std::uint8_t AgentResponseType; +typedef std::string AgentType; + +} // namespace Cynara + +#endif /* SRC_COMMON_TYPES_AGENT_H_ */ diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index b43bd1f..08f909c 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin.h ${CYNARA_PATH}/include/cynara-admin-types.h + ${CYNARA_PATH}/include/cynara-agent.h ${CYNARA_PATH}/include/cynara-client.h ${CYNARA_PATH}/include/cynara-client-async.h ${CYNARA_PATH}/include/cynara-client-plugin.h -- 2.7.4 From 67d6e25e9474be1b6c9d44d5534046c217ad9f11 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Wed, 12 Nov 2014 13:41:43 +0100 Subject: [PATCH 07/16] Fix answer callback call in asynchronous client Answer callback may modify check map by calling async client api functions within it. Check map is accessed after that call. Change-Id: Ifbf91f99cfa119e5524457f585b2779d7ae52558 --- src/client-async/callback/ResponseCallback.cpp | 6 ++++++ src/client-async/callback/ResponseCallback.h | 1 + src/client-async/check/CheckData.h | 5 +++++ src/client-async/logic/Logic.cpp | 6 ++++-- src/common/types/PolicyKey.h | 6 ++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp index 9307195..f904483 100644 --- a/src/client-async/callback/ResponseCallback.cpp +++ b/src/client-async/callback/ResponseCallback.cpp @@ -28,6 +28,12 @@ ResponseCallback::ResponseCallback(cynara_response_callback callback, void *user : m_callback(callback), m_userData(userData) { } +ResponseCallback::ResponseCallback(ResponseCallback &&other) + : m_callback(other.m_callback), m_userData(other.m_userData) { + other.m_callback = nullptr; + other.m_userData = nullptr; +} + void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const { if (!m_callback) return; diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h index 925d7f4..1af7291 100644 --- a/src/client-async/callback/ResponseCallback.h +++ b/src/client-async/callback/ResponseCallback.h @@ -31,6 +31,7 @@ class ResponseCallback { public: ResponseCallback(cynara_response_callback callback, void *userData); ResponseCallback(const ResponseCallback&) = default; + ResponseCallback(ResponseCallback &&other); ~ResponseCallback() {}; void onAnswer(cynara_check_id checkId, int response) const; diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h index a25abb3..453af76 100644 --- a/src/client-async/check/CheckData.h +++ b/src/client-async/check/CheckData.h @@ -38,6 +38,11 @@ class CheckData public: CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback) : m_key(key), m_session(session), m_callback(callback), m_cancelled(false) {} + CheckData(CheckData &&other) + : m_key(std::move(other.m_key)), m_session(std::move(other.m_session)), + m_callback(std::move(other.m_callback)), m_cancelled(other.m_cancelled) { + other.m_cancelled = false; + } ~CheckData() {} const PolicyKey &key(void) const { diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index bfb494c..9725d64 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -166,10 +166,12 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { } int result = m_cache->update(it->second.session(), it->second.key(), checkResponse->m_resultRef); - if (!it->second.cancelled()) - it->second.callback().onAnswer(static_cast(it->first), result); + CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); + if (!checkData.cancelled()) + checkData.callback().onAnswer( + static_cast(checkResponse->sequenceNumber()), result); } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/common/types/PolicyKey.h b/src/common/types/PolicyKey.h index 6bf0302..3f65c58 100644 --- a/src/common/types/PolicyKey.h +++ b/src/common/types/PolicyKey.h @@ -36,6 +36,9 @@ class PolicyKeyFeature { friend class PolicyKey; public: + PolicyKeyFeature(const PolicyKeyFeature &) = default; + PolicyKeyFeature(PolicyKeyFeature &&) = default; + typedef std::string ValueType; static PolicyKeyFeature create(ValueType value) { @@ -98,6 +101,9 @@ public: const PolicyKeyFeature::ValueType &privilegeId) : m_client(clientId), m_user(userId), m_privilege(privilegeId) {}; + PolicyKey(const PolicyKey &) = default; + PolicyKey(PolicyKey &&) = default; + bool operator==(const PolicyKey &other) const { return std::tie(m_client, m_user, m_privilege) == std::tie(other.m_client, other.m_user, other.m_privilege); -- 2.7.4 From a62008b94c1460be31fa9fc53f784c0d5fcbd1a7 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 13:18:32 +0100 Subject: [PATCH 08/16] Forbid some operations in asynchronous callbacks In following cases cynara api operations regarding same cynara_async structure called from within callbacks will return CYNARA_API_OPERATION_NOT_ALLOWED: - always within cynara_status_callback - within cynara_response_callback called with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause. It regards following api funtions: - cynara_async_check_cache() - cynara_async_create_request() - cynara_async_process() - cynara_async_cancel_request() Change-Id: I1db22e0735e1905c4709c7f4c650cc8ca3f9b454 --- src/client-async/logic/Logic.cpp | 42 +++++++++++++++++++++++++++++---------- src/client-async/logic/Logic.h | 2 ++ src/include/cynara-client-async.h | 19 +++++++++++++++--- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 9725d64..5e0157d 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,7 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -55,6 +55,7 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) } Logic::~Logic() { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onFinish(kv.first); @@ -64,6 +65,9 @@ Logic::~Logic() { int Logic::checkCache(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!checkCacheValid()) return CYNARA_API_CACHE_MISS; @@ -74,6 +78,9 @@ int Logic::createRequest(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege, cynara_check_id &checkId, cynara_response_callback callback, void *userResponseData) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -86,14 +93,16 @@ int Logic::createRequest(const std::string &client, const std::string &session, m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback))); m_socketClient->appendRequest(std::make_shared(key, sequenceNumber)); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); checkId = static_cast(sequenceNumber); return CYNARA_API_SUCCESS; } int Logic::process(void) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + bool completed; while (true) { int ret = completeConnection(completed); @@ -108,6 +117,9 @@ int Logic::process(void) { } int Logic::cancelRequest(cynara_check_id checkId) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -119,8 +131,7 @@ int Logic::cancelRequest(cynara_check_id checkId) { it->second.cancel(); it->second.callback().onCancel(it->first); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } @@ -144,8 +155,8 @@ void Logic::prepareRequestsToSend(void) { bool Logic::processOut(void) { switch (m_socketClient->sendToCynara()) { case Socket::SendStatus::ALL_DATA_SENT: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_READ); + onStatusChange(m_socketClient->getSockFd(), + cynara_async_status::CYNARA_STATUS_FOR_READ); case Socket::SendStatus::PARTIAL_DATA_SENT: return true; default: @@ -238,12 +249,11 @@ bool Logic::connect(void) { switch (m_socketClient->connect()) { case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); return true; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return true; default: onServiceNotAvailable(); @@ -257,7 +267,7 @@ int Logic::completeConnection(bool &completed) { completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: @@ -271,19 +281,29 @@ int Logic::completeConnection(bool &completed) { } } +void Logic::onStatusChange(int sock, cynara_async_status status) { + m_operationPermitted = false; + m_statusCallback.onStatusChange(sock, status); + m_operationPermitted = true; +} + void Logic::onServiceNotAvailable(void) { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onDisconnected(kv.first); } m_checks.clear(); m_sequenceContainer.clear(); + m_operationPermitted = true; } void Logic::onDisconnected(void) { + m_operationPermitted = false; m_cache->clear(); m_statusCallback.onDisconnected(); + m_operationPermitted = true; } } // namespace Cynara diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 0bca98e..6f30fdb 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -59,6 +59,7 @@ private: SocketClientAsyncPtr m_socketClient; CheckMap m_checks; SequenceContainer m_sequenceContainer; + bool m_operationPermitted; bool checkCacheValid(void); void prepareRequestsToSend(void); @@ -71,6 +72,7 @@ private: bool ensureConnection(void); bool connect(void); int completeConnection(bool &completed); + void onStatusChange(int sock, cynara_async_status status); void onServiceNotAvailable(void); void onDisconnected(void); }; diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index 536e5d7..b9675f1 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -84,6 +84,8 @@ typedef enum { * (CYNARA_CALL_CAUSE_FINISH) * 4) when connection to cynara service was broken and cannot be established again * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) + * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -113,6 +115,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * Note, that provided file descriptor is used internally by libcynara * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. + * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -240,7 +243,10 @@ void cynara_async_finish(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_check_cache() needs cynara_async structure to be created first. - * Use cynara_async_initialize() before calling this function. + * Use cynara_async_initialize() before calling this function. cynara_async_check_cache() called + * from within cynara_status_callback or cynara_response_callback with + * CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause will return + * CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -306,6 +312,9 @@ int cynara_async_check_cache(cynara_async *p_cynara, const char *client, const c * If function fails (returns negative error code) request won't be generated and won't be pending, * callback function won't be ever called and user_response_data won't be remembered by library. * Also no check_id will be generated and *p_check_id value should be ignored. + * cynara_async_create_request() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -359,7 +368,9 @@ int cynara_async_create_request(cynara_async *p_cynara, const char *client, * * \par Important notes: * Call to cynara_async_process() requires initialized cynara_async structure. For this use - * cynara_async_initialize(). + * cynara_async_initialize(). cynara_async_process() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * @@ -398,7 +409,9 @@ int cynara_async_process(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_cancel_request() needs cynara_async structure to be created first. For this - * use cynara_async_initialize(). + * use cynara_async_initialize(). cynara_async_cancel_request() called from within + * cynara_status_callback or cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] check_id Check id to be cancelled -- 2.7.4 From bf838ebf47eabea59dae47d83f1fdc360693f5cb Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 18:48:01 +0100 Subject: [PATCH 09/16] Add protection against cynara_async_finish() call in callbacks cynara_async_finish() called in callbacks is ignored in all cases. Change-Id: I3c2268a0462413b279215f837e4603a7d6acb96d --- src/client-async/api/ApiInterface.h | 1 + src/client-async/api/client-async-api.cpp | 3 +++ src/client-async/logic/Logic.cpp | 18 ++++++++++++++++-- src/client-async/logic/Logic.h | 2 ++ src/include/cynara-client-async.h | 4 ++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/client-async/api/ApiInterface.h b/src/client-async/api/ApiInterface.h index 31478da..59c82fb 100644 --- a/src/client-async/api/ApiInterface.h +++ b/src/client-async/api/ApiInterface.h @@ -42,6 +42,7 @@ public: void *userResponseData) = 0; virtual int process(void) = 0; virtual int cancelRequest(cynara_check_id checkId) = 0; + virtual bool isFinishPermitted(void) = 0; }; } // namespace Cynara diff --git a/src/client-async/api/client-async-api.cpp b/src/client-async/api/client-async-api.cpp index 1e3479e..13e5a16 100644 --- a/src/client-async/api/client-async-api.cpp +++ b/src/client-async/api/client-async-api.cpp @@ -61,6 +61,9 @@ int cynara_async_initialize(cynara_async **pp_cynara, CYNARA_API void cynara_async_finish(cynara_async *p_cynara) { + if (!p_cynara->impl->isFinishPermitted()) + return; + delete p_cynara; } diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 5e0157d..48b8bad 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,8 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true), + m_inAnswerCancelResponseCallback(false) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -130,12 +131,21 @@ int Logic::cancelRequest(cynara_check_id checkId) { m_socketClient->appendRequest(std::make_shared(it->first)); it->second.cancel(); + + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; it->second.callback().onCancel(it->first); + m_inAnswerCancelResponseCallback = onAnswerCancel; + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } +bool Logic::isFinishPermitted(void) { + return m_operationPermitted && !m_inAnswerCancelResponseCallback; +} + bool Logic::checkCacheValid(void) { return m_socketClient->isConnected(); } @@ -180,9 +190,13 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); - if (!checkData.cancelled()) + if (!checkData.cancelled()) { + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; checkData.callback().onAnswer( static_cast(checkResponse->sequenceNumber()), result); + m_inAnswerCancelResponseCallback = onAnswerCancel; + } } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 6f30fdb..6d41412 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -49,6 +49,7 @@ public: void *userResponseData); virtual int process(void); virtual int cancelRequest(cynara_check_id checkId); + virtual bool isFinishPermitted(void); private: typedef std::map CheckMap; @@ -60,6 +61,7 @@ private: CheckMap m_checks; SequenceContainer m_sequenceContainer; bool m_operationPermitted; + bool m_inAnswerCancelResponseCallback; bool checkCacheValid(void); void prepareRequestsToSend(void); diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index b9675f1..d9b4d2f 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -86,6 +86,7 @@ typedef enum { * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -116,6 +117,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -207,6 +209,8 @@ int cynara_async_initialize(cynara_async **pp_cynara, const cynara_async_configu * * \par Important notes: * No other call to cynara-async-client library should be made after call to cynara_async_finish(). + * cynara_async_finish() called from within cynara_response_callback or cynara_status_callback will + * be ignored. * * \param[in] p_cynara cynara_async structure. If NULL, then the call has no effect. */ -- 2.7.4 From fee91a55de39cc66ac4f0b4e9c3936874f1aa3d9 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 2 Oct 2014 14:06:45 +0200 Subject: [PATCH 10/16] Implement agent<->cynara communication layer Only agent side communication layer was implemented. Also protocol is not implemented. Change-Id: Ic11bd0ea92284c98366a7f833f0d339f2784dad0 --- src/agent/CMakeLists.txt | 1 + src/agent/logic/Logic.cpp | 118 ++++++++++++++++++++++++-- src/agent/logic/Logic.h | 8 ++ src/agent/socket/AgentSocketClient.cpp | 102 ++++++++++++++++++++++ src/agent/socket/AgentSocketClient.h | 69 +++++++++++++++ src/common/CMakeLists.txt | 3 + src/common/protocol/ProtocolAgent.cpp | 11 +++ src/common/protocol/ProtocolAgent.h | 3 + src/common/request/AgentActionRequest.cpp | 36 ++++++++ src/common/request/AgentActionRequest.h | 60 +++++++++++++ src/common/request/AgentRegisterRequest.cpp | 36 ++++++++ src/common/request/AgentRegisterRequest.h | 53 ++++++++++++ src/common/request/RequestTaker.cpp | 8 ++ src/common/request/RequestTaker.h | 2 + src/common/request/pointers.h | 3 + src/common/response/AgentRegisterResponse.cpp | 36 ++++++++ src/common/response/AgentRegisterResponse.h | 53 ++++++++++++ src/common/response/ResponseTaker.cpp | 4 + src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 + 20 files changed, 602 insertions(+), 8 deletions(-) create mode 100644 src/agent/socket/AgentSocketClient.cpp create mode 100644 src/agent/socket/AgentSocketClient.h create mode 100644 src/common/request/AgentActionRequest.cpp create mode 100644 src/common/request/AgentActionRequest.h create mode 100644 src/common/request/AgentRegisterRequest.cpp create mode 100644 src/common/request/AgentRegisterRequest.h create mode 100644 src/common/response/AgentRegisterResponse.cpp create mode 100644 src/common/response/AgentRegisterResponse.h diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index 1f31692..83d90f6 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -24,6 +24,7 @@ SET(CYNARA_LIB_CYNARA_AGENT_PATH ${CYNARA_PATH}/agent) SET(LIB_CYNARA_AGENT_SOURCES ${CYNARA_LIB_CYNARA_AGENT_PATH}/api/agent-api.cpp ${CYNARA_LIB_CYNARA_AGENT_PATH}/logic/Logic.cpp + ${CYNARA_LIB_CYNARA_AGENT_PATH}/socket/AgentSocketClient.cpp ) INCLUDE_DIRECTORIES( diff --git a/src/agent/logic/Logic.cpp b/src/agent/logic/Logic.cpp index b8a66d4..d6576fe 100644 --- a/src/agent/logic/Logic.cpp +++ b/src/agent/logic/Logic.cpp @@ -20,28 +20,130 @@ * @brief This file contains implementation of Logic class - main libcynara-agent class */ +#include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include "Logic.h" +namespace { + +Cynara::ProtocolFrameSequenceNumber generateSequenceNumber(void) { + static Cynara::ProtocolFrameSequenceNumber sequenceNumber = 0; + return ++sequenceNumber; +} + +} // namespace anonymous + namespace Cynara { -Logic::Logic(const AgentType &agentType) : m_agentType(agentType) { +Logic::Logic(const AgentType &agentType) : m_agentType(agentType), m_registered(false) { + m_agentSocket = std::make_shared(PathConfig::SocketPath::agent, + std::make_shared()); + m_responseTakerPtr = std::make_shared(); + m_responseBuffer = std::make_shared(); } -int Logic::getRequest(AgentActionResponsePtr &resultPtr UNUSED) { - // TODO: implement - return CYNARA_API_SUCCESS; +int Logic::registerInCynara(void) { + ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); + + //Ask cynara service + AgentRegisterResponsePtr registerResponsePtr; + RequestPtr request = std::make_shared(m_agentType, sequenceNumber); + ResponsePtr response = m_agentSocket->askCynaraServer(request); + if (!response) { + LOGW("Disconnected by cynara server."); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } + + registerResponsePtr = std::dynamic_pointer_cast(response); + if (!registerResponsePtr) { + LOGC("Casting response to AgentRegisterResponse failed."); + return CYNARA_API_UNKNOWN_ERROR; + } + LOGD("registerResponse: answer code [%d]", static_cast(registerResponsePtr->m_code)); + + switch (registerResponsePtr->m_code) { + case AgentRegisterResponse::DONE: + return CYNARA_API_SUCCESS; + case AgentRegisterResponse::REJECTED: + LOGE("Registering agent of type <%s> has been rejected", m_agentType.c_str()); + return CYNARA_API_ACCESS_DENIED; + default: + LOGE("Registering agent of type <%s> has finished with unknown error", + m_agentType.c_str()); + return CYNARA_API_UNKNOWN_ERROR; + } } -int Logic::putResponse(const AgentResponseType responseType UNUSED, - const ProtocolFrameSequenceNumber sequenceNumber UNUSED, - const RawBuffer &pluginData UNUSED) { +int Logic::ensureConnection(void) { + switch (m_agentSocket->connect()) { + case SS_CONNECTED: + return CYNARA_API_SUCCESS; + case SS_RECONNECTED: + return registerInCynara(); + case SS_DISCONNECTED: + LOGE("Agent socket disconnected."); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } - // TODO: implement + return CYNARA_API_UNKNOWN_ERROR; +} + +int Logic::getRequest(AgentActionResponsePtr &resultPtr) { + int ret = ensureConnection(); + if (ret != CYNARA_API_SUCCESS) + return ret; + + ResponsePtr responsePtr = m_agentSocket->receiveResponseFromServer(); + if (!responsePtr) { + LOGW("Disconnected by cynara server."); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } + + AgentActionResponsePtr actionResponsePtr = + std::dynamic_pointer_cast(responsePtr); + if (!actionResponsePtr) { + LOGC("Casting request to AgentActionResponse failed."); + return CYNARA_API_UNKNOWN_ERROR; + } + LOGD("agentActionResponse: type: [%" PRIu8 "], data length: [%zu]", + actionResponsePtr->type(), actionResponsePtr->data().size()); + + resultPtr = actionResponsePtr; return CYNARA_API_SUCCESS; } +int Logic::putResponse(const AgentResponseType responseType, + const ProtocolFrameSequenceNumber sequenceNumber, + const RawBuffer &pluginData) { + if (!m_agentSocket->isConnected()) { + LOGE("Agent not connected to cynara service."); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } + + RequestPtr requestPtr = std::make_shared(responseType, pluginData, + sequenceNumber); + m_responseBuffer->clear(); + RequestContextPtr contextPtr = std::make_shared(ResponseTakerPtr(), + m_responseBuffer); + requestPtr->execute(requestPtr, m_responseTakerPtr, contextPtr); + return m_agentSocket->sendDataToServer(*m_responseBuffer) ? CYNARA_API_SUCCESS : + CYNARA_API_SERVICE_NOT_AVAILABLE; +} + } // namespace Cynara diff --git a/src/agent/logic/Logic.h b/src/agent/logic/Logic.h index facead7..e8ff3e7 100644 --- a/src/agent/logic/Logic.h +++ b/src/agent/logic/Logic.h @@ -26,6 +26,7 @@ #include #include +#include namespace Cynara { @@ -42,6 +43,13 @@ public: private: AgentType m_agentType; + AgentSocketPtr m_agentSocket; + bool m_registered; + RequestTakerPtr m_responseTakerPtr; + BinaryQueuePtr m_responseBuffer; + + int registerInCynara(void); + int ensureConnection(void); }; } // namespace Cynara diff --git a/src/agent/socket/AgentSocketClient.cpp b/src/agent/socket/AgentSocketClient.cpp new file mode 100644 index 0000000..780c996 --- /dev/null +++ b/src/agent/socket/AgentSocketClient.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/socket/AgentSocket.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains implementation of agent socket client + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "AgentSocketClient.h" + +namespace Cynara { + +AgentSocketClient::AgentSocketClient(const std::string &socketPath, ProtocolPtr protocol) + : m_socket(socketPath), m_protocol(protocol) { + m_writeQueue = std::make_shared(); + m_readQueue = std::make_shared(); +} + +ResponsePtr AgentSocketClient::askCynaraServer(RequestPtr request) { + //pass request to protocol + RequestContextPtr context = std::make_shared(ResponseTakerPtr(), m_writeQueue); + request->execute(request, m_protocol, context); + + //send request to cynara + if (!sendDataToServer(*m_writeQueue)) { + return nullptr; + } + + // receive response from cynara + return receiveResponseFromServer(); +} + +ResponsePtr AgentSocketClient::receiveResponseFromServer(void) { + while (true) { + if (!m_socket.receiveFromServer(*m_readQueue)) { + LOGW("Error receiving data from Cynara. Service not available."); + return nullptr; + } + + ResponsePtr response = m_protocol->extractResponseFromBuffer(m_readQueue); + if (response) { + return response; + } + } +} + +bool AgentSocketClient::sendDataToServer(BinaryQueue &data) { + if (m_socket.sendToServer(data) == Socket::SendStatus::CONNECTION_LOST) { + LOGW("Error sending data to Cynara. Service not available."); + return false; + } + + return true; +} + +bool AgentSocketClient::isConnected(void) { + return m_socket.isConnected(); +} + +AgentSocketState AgentSocketClient::connect(void) { + if (isConnected()) + return SS_CONNECTED; + + if (m_socket.connect() == Socket::ConnectionStatus::CONNECTION_SUCCEEDED) { + resetState(); + return SS_RECONNECTED; + } + + return SS_DISCONNECTED; +} + +void AgentSocketClient::resetState(void) { + m_readQueue->clear(); + m_writeQueue->clear(); +} + +} // namespace Cynara diff --git a/src/agent/socket/AgentSocketClient.h b/src/agent/socket/AgentSocketClient.h new file mode 100644 index 0000000..ee58c49 --- /dev/null +++ b/src/agent/socket/AgentSocketClient.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014 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 + */ +/** + * @file src/agent/socket/AgentSocketClient.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains definition of agent socket client + */ + +#ifndef SRC_AGENT_SOCKET_AGENTSOCKETCLIENT_H_ +#define SRC_AGENT_SOCKET_AGENTSOCKETCLIENT_H_ + +#include +#include + +#include +#include +#include +#include +#include + +namespace Cynara { + +class AgentSocketClient; +typedef std::shared_ptr AgentSocketPtr; + +typedef enum { + SS_DISCONNECTED, + SS_CONNECTED, + SS_RECONNECTED, +} AgentSocketState; + +class AgentSocketClient { +public: + AgentSocketClient(const std::string &socketPath, ProtocolPtr protocol); + virtual ~AgentSocketClient() {}; + + bool isConnected(void); + AgentSocketState connect(void); + + ResponsePtr receiveResponseFromServer(void); + bool sendDataToServer(BinaryQueue &data); + ResponsePtr askCynaraServer(RequestPtr request); + +private: + Socket m_socket; + ProtocolPtr m_protocol; + BinaryQueuePtr m_readQueue; + BinaryQueuePtr m_writeQueue; + + void resetState(void); +}; + +} // namespace Cynara + +#endif /* SRC_AGENT_SOCKET_AGENTSOCKETCLIENT_H_ */ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 42f66eb..7f3da76 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -39,6 +39,8 @@ SET(COMMON_SOURCES ${COMMON_PATH}/protocol/ProtocolSerialization.cpp ${COMMON_PATH}/protocol/ProtocolSignal.cpp ${COMMON_PATH}/request/AdminCheckRequest.cpp + ${COMMON_PATH}/request/AgentActionRequest.cpp + ${COMMON_PATH}/request/AgentRegisterRequest.cpp ${COMMON_PATH}/request/CancelRequest.cpp ${COMMON_PATH}/request/CheckRequest.cpp ${COMMON_PATH}/request/InsertOrUpdateBucketRequest.cpp @@ -47,6 +49,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/SetPoliciesRequest.cpp ${COMMON_PATH}/request/SignalRequest.cpp ${COMMON_PATH}/response/AgentActionResponse.cpp + ${COMMON_PATH}/response/AgentRegisterResponse.cpp ${COMMON_PATH}/response/CancelResponse.cpp ${COMMON_PATH}/response/CheckResponse.cpp ${COMMON_PATH}/response/CodeResponse.cpp diff --git a/src/common/protocol/ProtocolAgent.cpp b/src/common/protocol/ProtocolAgent.cpp index f4d26a1..7d85d31 100644 --- a/src/common/protocol/ProtocolAgent.cpp +++ b/src/common/protocol/ProtocolAgent.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -81,4 +82,14 @@ ResponsePtr ProtocolAgent::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) return nullptr; } +void ProtocolAgent::execute(RequestContextPtr context UNUSED, + AgentActionRequestPtr request UNUSED) { + //TODO: implement +} + +void ProtocolAgent::execute(RequestContextPtr context UNUSED, + AgentActionResponsePtr request UNUSED) { + //TODO: implement +} + } // namespace Cynara diff --git a/src/common/protocol/ProtocolAgent.h b/src/common/protocol/ProtocolAgent.h index 68baf46..92fb788 100644 --- a/src/common/protocol/ProtocolAgent.h +++ b/src/common/protocol/ProtocolAgent.h @@ -40,6 +40,9 @@ public: virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); + + virtual void execute(RequestContextPtr context, AgentActionRequestPtr request); + virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); }; } // namespace Cynara diff --git a/src/common/request/AgentActionRequest.cpp b/src/common/request/AgentActionRequest.cpp new file mode 100644 index 0000000..1e51313 --- /dev/null +++ b/src/common/request/AgentActionRequest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/request/AgentActionRequest.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements agent action request class + */ + +#include + +#include + +#include "AgentActionRequest.h" + +namespace Cynara { + +void AgentActionRequest::execute(RequestPtr self, RequestTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/AgentActionRequest.h b/src/common/request/AgentActionRequest.h new file mode 100644 index 0000000..f187435 --- /dev/null +++ b/src/common/request/AgentActionRequest.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/request/AgentActionRequest.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines agent register request class + */ + +#ifndef SRC_COMMON_REQUEST_AGENTACTIONTREQUEST_H_ +#define SRC_COMMON_REQUEST_AGENTACTIONTREQUEST_H_ + +#include + +#include +#include +#include + +namespace Cynara { + +class AgentActionRequest : public Request { +public: + AgentActionRequest(const AgentRequestType type, const RawBuffer &data, + ProtocolFrameSequenceNumber sequenceNumber) : Request(sequenceNumber), + m_type(type), m_data(data) { + } + + virtual ~AgentActionRequest() {}; + + const RawBuffer &data(void) const { + return m_data; + } + + AgentRequestType type(void) const { + return m_type; + } + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; + +private: + const AgentRequestType m_type; + const RawBuffer m_data; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_AGENTACTIONTREQUEST_H_ */ diff --git a/src/common/request/AgentRegisterRequest.cpp b/src/common/request/AgentRegisterRequest.cpp new file mode 100644 index 0000000..6488193 --- /dev/null +++ b/src/common/request/AgentRegisterRequest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/request/AgentRegisterRequest.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements agent register request class + */ + +#include + +#include + +#include "AgentRegisterRequest.h" + +namespace Cynara { + +void AgentRegisterRequest::execute(RequestPtr self, RequestTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/AgentRegisterRequest.h b/src/common/request/AgentRegisterRequest.h new file mode 100644 index 0000000..aa6f61b --- /dev/null +++ b/src/common/request/AgentRegisterRequest.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/request/AgentRegisterRequest.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines agent register request class + */ + +#ifndef SRC_COMMON_REQUEST_AGENTREGISTERREQUEST_H_ +#define SRC_COMMON_REQUEST_AGENTREGISTERREQUEST_H_ + +#include + +#include +#include + +namespace Cynara { + +class AgentRegisterRequest : public Request { +public: + AgentRegisterRequest(const AgentType &agentType, ProtocolFrameSequenceNumber sequenceNumber) : + Request(sequenceNumber), m_agentType(agentType) { + } + + virtual ~AgentRegisterRequest() {}; + + const AgentType &agentType(void) const { + return m_agentType; + } + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; + +private: + AgentType m_agentType; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_AGENTREGISTERREQUEST_H_ */ diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index a4d7c2d..f46d428 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -33,6 +33,14 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, AdminCheckRequestPt throw NotImplementedException(); } +void RequestTaker::execute(RequestContextPtr context UNUSED, AgentActionRequestPtr request UNUSED) { + throw NotImplementedException(); +} + +void RequestTaker::execute(RequestContextPtr context UNUSED, AgentRegisterRequestPtr request UNUSED) { + throw NotImplementedException(); +} + void RequestTaker::execute(RequestContextPtr context UNUSED, CancelRequestPtr request UNUSED) { throw NotImplementedException(); } diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index 522d8bb..f190e69 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -33,6 +33,8 @@ public: virtual ~RequestTaker() {}; virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); + virtual void execute(RequestContextPtr context, AgentActionRequestPtr request); + virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index e20a6ad..19429a9 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -33,6 +33,9 @@ typedef std::shared_ptr AdminCheckRequestPtr; class AgentActionRequest; typedef std::shared_ptr AgentActionRequestPtr; +class AgentRegisterRequest; +typedef std::shared_ptr AgentRegisterRequestPtr; + class CancelRequest; typedef std::shared_ptr CancelRequestPtr; diff --git a/src/common/response/AgentRegisterResponse.cpp b/src/common/response/AgentRegisterResponse.cpp new file mode 100644 index 0000000..fe15bd3 --- /dev/null +++ b/src/common/response/AgentRegisterResponse.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/response/AgentRegisterResponse.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements class for responding to agent register request + */ + +#include + +#include + +#include "AgentRegisterResponse.h" + +namespace Cynara { + +void AgentRegisterResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/AgentRegisterResponse.h b/src/common/response/AgentRegisterResponse.h new file mode 100644 index 0000000..0b8f678 --- /dev/null +++ b/src/common/response/AgentRegisterResponse.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/response/AgentRegisterResponse.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines class for responding to agent register request + */ + +#ifndef SRC_COMMON_RESPONSE_AGENTREGISTERRESPONSE_H_ +#define SRC_COMMON_RESPONSE_AGENTREGISTERRESPONSE_H_ + +#include +#include +#include + +namespace Cynara { + +class AgentRegisterResponse : public Response { +public: + enum Code { + DONE, + REJECTED, + ERROR + }; + + const Code m_code; + + AgentRegisterResponse(Code code, ProtocolFrameSequenceNumber sequenceNumber) : + Response(sequenceNumber), m_code(code) { + } + + virtual ~AgentRegisterResponse() {}; + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, RequestContextPtr context) const; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_AGENTREGISTERRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index 34f84f5..cf5ae40 100644 --- a/src/common/response/ResponseTaker.cpp +++ b/src/common/response/ResponseTaker.cpp @@ -32,6 +32,10 @@ void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentActionRespons throw NotImplementedException(); } +void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentRegisterResponsePtr response UNUSED) { + throw NotImplementedException(); +} + void ResponseTaker::execute(RequestContextPtr context UNUSED, CancelResponsePtr response UNUSED) { throw NotImplementedException(); } diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 1642072..6256e73 100644 --- a/src/common/response/ResponseTaker.h +++ b/src/common/response/ResponseTaker.h @@ -34,6 +34,7 @@ public: virtual ~ResponseTaker() {}; virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); + virtual void execute(RequestContextPtr context, AgentRegisterResponsePtr response); virtual void execute(RequestContextPtr context, CancelResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); diff --git a/src/common/response/pointers.h b/src/common/response/pointers.h index 1774a4b..378fed4 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -30,6 +30,9 @@ namespace Cynara { class AgentActionResponse; typedef std::shared_ptr AgentActionResponsePtr; +class AgentRegisterResponse; +typedef std::shared_ptr AgentRegisterResponsePtr; + class CancelResponse; typedef std::shared_ptr CancelResponsePtr; -- 2.7.4 From 0835cbb5a4be5898ce08d01f11e662009657626a Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 9 Oct 2014 14:44:42 +0200 Subject: [PATCH 11/16] Implement agent protocol layer This patch contains implementation of (de)serializer class for agent protocol. Change-Id: I8ac7b5816545bd8e76a50d66a84b8ac686125985 --- src/common/protocol/ProtocolAgent.cpp | 126 ++++++++++++++++++++++++++++++---- src/common/protocol/ProtocolAgent.h | 10 ++- src/common/protocol/ProtocolOpCode.h | 8 +++ 3 files changed, 130 insertions(+), 14 deletions(-) diff --git a/src/common/protocol/ProtocolAgent.cpp b/src/common/protocol/ProtocolAgent.cpp index 7d85d31..7ccec81 100644 --- a/src/common/protocol/ProtocolAgent.cpp +++ b/src/common/protocol/ProtocolAgent.cpp @@ -23,12 +23,16 @@ #include #include -#include #include #include #include #include #include +#include +#include +#include +#include +#include #include "ProtocolAgent.h" @@ -44,6 +48,29 @@ ProtocolPtr ProtocolAgent::clone(void) { return std::make_shared(); } +RequestPtr ProtocolAgent::deserializeActionRequest(void) { + AgentRequestType requestType; + RawBuffer data; + + ProtocolDeserialization::deserialize(m_frameHeader, requestType); + ProtocolDeserialization::deserialize(m_frameHeader, data); + + LOGD("Deserialized AgentActionRequest: requestType [%" PRIu8 "], data lengtgh <%zu>", + requestType, data.size()); + + return std::make_shared(requestType, data, m_frameHeader.sequenceNumber()); +} + +RequestPtr ProtocolAgent::deserializeRegisterRequest(void) { + AgentType agentType; + + ProtocolDeserialization::deserialize(m_frameHeader, agentType); + + LOGD("Deserialized AgentRegisterRequest: agent type <%s>", agentType.c_str()); + + return std::make_shared(agentType, m_frameHeader.sequenceNumber()); +} + RequestPtr ProtocolAgent::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); @@ -54,15 +81,44 @@ RequestPtr ProtocolAgent::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolDeserialization::deserialize(m_frameHeader, opCode); LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { - default: - throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); - break; + case OpAgentActionRequest: + return deserializeActionRequest(); + case OpAgentRegisterRequest: + return deserializeRegisterRequest(); + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; } } return nullptr; } +ResponsePtr ProtocolAgent::deserializeActionResponse(void) { + AgentResponseType responseType; + RawBuffer data; + + ProtocolDeserialization::deserialize(m_frameHeader, responseType); + ProtocolDeserialization::deserialize(m_frameHeader, data); + + LOGD("Deserialized AgentActionResponse: responseType [%" PRIu8 "], data lengtgh <%zu>", + responseType, data.size()); + + return std::make_shared(responseType, data, + m_frameHeader.sequenceNumber()); +} + +ResponsePtr ProtocolAgent::deserializeRegisterResponse(void) { + ProtocolResponseCode result; + + ProtocolDeserialization::deserialize(m_frameHeader, result); + + LOGD("Deserialized AgentRegisterResponse: result [%d]", static_cast(result)); + + return std::make_shared(static_cast(result), + m_frameHeader.sequenceNumber()); +} + ResponsePtr ProtocolAgent::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); @@ -73,23 +129,67 @@ ResponsePtr ProtocolAgent::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) ProtocolDeserialization::deserialize(m_frameHeader, opCode); LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { - default: - throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); - break; + case OpAgentActionResponse: + return deserializeActionResponse(); + case OpAgentRegisterResponse: + return deserializeRegisterResponse(); + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; } } return nullptr; } -void ProtocolAgent::execute(RequestContextPtr context UNUSED, - AgentActionRequestPtr request UNUSED) { - //TODO: implement +void ProtocolAgent::execute(RequestContextPtr context, AgentActionRequestPtr request) { + LOGD("Serializing AgentActionRequest: op [%" PRIu8 "], requestType [%" PRIu8 "], " + "data lengtgh <%zu>", OpAgentActionRequest, request->type(), request->data().size()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAgentActionRequest); + ProtocolSerialization::serialize(frame, request->type()); + ProtocolSerialization::serialize(frame, request->data()); + + ProtocolFrameSerializer::finishSerialization(frame, *context->responseQueue()); +} + +void ProtocolAgent::execute(RequestContextPtr context, AgentRegisterRequestPtr request) { + LOGD("Serializing AgentRegisterRequest: op [%" PRIu8 "], agent type <%s>", + OpAgentRegisterRequest, request->agentType().c_str()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAgentRegisterRequest); + ProtocolSerialization::serialize(frame, request->agentType()); + + ProtocolFrameSerializer::finishSerialization(frame, *context->responseQueue()); +} + +void ProtocolAgent::execute(RequestContextPtr context, AgentRegisterResponsePtr response) { + LOGD("Serializing AgentRegisterResponse: op [%" PRIu8 "], response code: [%d]", + OpAgentRegisterResponse, static_cast(response->m_code)); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(response->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAgentRegisterResponse); + ProtocolSerialization::serialize(frame, static_cast(response->m_code)); + + ProtocolFrameSerializer::finishSerialization(frame, *context->responseQueue()); } -void ProtocolAgent::execute(RequestContextPtr context UNUSED, - AgentActionResponsePtr request UNUSED) { - //TODO: implement +void ProtocolAgent::execute(RequestContextPtr context, AgentActionResponsePtr response) { + LOGD("Serializing AgentActionResponse: op [%" PRIu8 "], responseType [%" PRIu8 "], " + "data lengtgh <%zu>", OpAgentActionResponse, response->type(), response->data().size()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(response->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAgentActionResponse); + ProtocolSerialization::serialize(frame, response->type()); + ProtocolSerialization::serialize(frame, response->data()); + + ProtocolFrameSerializer::finishSerialization(frame, *context->responseQueue()); } } // namespace Cynara diff --git a/src/common/protocol/ProtocolAgent.h b/src/common/protocol/ProtocolAgent.h index 92fb788..ca28ec7 100644 --- a/src/common/protocol/ProtocolAgent.h +++ b/src/common/protocol/ProtocolAgent.h @@ -42,7 +42,15 @@ public: virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); virtual void execute(RequestContextPtr context, AgentActionRequestPtr request); - virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); + virtual void execute(RequestContextPtr context, AgentActionResponsePtr request); + virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); + virtual void execute(RequestContextPtr context, AgentRegisterResponsePtr request); + +private: + RequestPtr deserializeActionRequest(void); + RequestPtr deserializeRegisterRequest(void); + ResponsePtr deserializeActionResponse(void); + ResponsePtr deserializeRegisterResponse(void); }; } // namespace Cynara diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 2b4171c..7bd67ae 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -44,6 +44,14 @@ enum ProtocolOpCode : uint8_t { OpSetPolicies, OpCodeResponse, OpAdminCheckRequest, + + /** Opcodes 25 - 39 are reserved for future use */ + + /** Agent operations */ + OpAgentRegisterRequest = 40, + OpAgentRegisterResponse, + OpAgentActionRequest, + OpAgentActionResponse, }; } /* namespace Cynara */ -- 2.7.4 From c928edeb1753be9aed51016c44a171548b85421d Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 14 Oct 2014 09:39:46 +0200 Subject: [PATCH 12/16] Add AgentRegisterRequest handling Simple mockup of registering agent in cynara service. Change-Id: I8368c6ad1af946c86e44d196f073d1bf209e97c3 --- src/service/logic/Logic.cpp | 21 +++++++++++++++------ src/service/logic/Logic.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index d4cc634..55f9f63 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -20,10 +20,11 @@ * @brief This file implements main class of logic layer in cynara service */ -#include +#include +#include -#include #include +#include #include #include #include @@ -32,11 +33,8 @@ #include #include #include - -#include - -#include
#include +#include #include #include #include @@ -44,12 +42,17 @@ #include #include #include +#include #include #include #include + +#include
#include #include +#include + #include "Logic.h" namespace Cynara { @@ -78,6 +81,12 @@ void Logic::execute(RequestContextPtr context, AdminCheckRequestPtr request) { request->sequenceNumber())); } +void Logic::execute(RequestContextPtr context, AgentRegisterRequestPtr request) { + // MOCKUP + context->returnResponse(context, std::make_shared( + AgentRegisterResponse::DONE, request->sequenceNumber())); +} + void Logic::execute(RequestContextPtr context, CancelRequestPtr request) { // MOCKUP context->returnResponse(context, std::make_shared(request->sequenceNumber())); diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index e74cffe..18d8abb 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -57,6 +57,7 @@ public: } virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); + virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); -- 2.7.4 From fa2034d81afa540bf2a944289b44c97321c57719 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 24 Oct 2014 19:14:12 +0200 Subject: [PATCH 13/16] Set all needed socket descriptors to write state Now every socket that has data to write is set to write state after any event on any socket descriptor. Before only part of them were set. This change is needed to send requests to extension agents. Change-Id: Id0d9ed2e73f748bac27d1f5e3e1fd22a7a2bb816 --- src/service/sockets/SocketManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index e454271..b7329b0 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -112,6 +112,9 @@ void SocketManager::mainLoop(void) { readyForWrite(i); --ret; } + } + + for (int i = 0; i < m_maxDesc + 1; ++i) { if (m_fds[i].isUsed() && m_fds[i].hasDataToWrite()) addWriteSocket(i); } -- 2.7.4 From 9ce6ffbb9656fd0682db12e9f94ad13465b6fe86 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 14 Nov 2014 18:58:37 +0100 Subject: [PATCH 14/16] Add LinkId type This type will be used to identify clients and agents. Change-Id: I6f6808919a6c8694ad8c3e51d826dc223541325f --- src/common/types/Link.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/common/types/Link.h diff --git a/src/common/types/Link.h b/src/common/types/Link.h new file mode 100644 index 0000000..d5a80a6 --- /dev/null +++ b/src/common/types/Link.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/common/types/Link.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines client connection related types + */ + +#ifndef SRC_COMMON_TYPES_LINK_H_ +#define SRC_COMMON_TYPES_LINK_H_ + +#include + +namespace Cynara { + +typedef BinaryQueuePtr LinkId; + +} // namespace Cynara + +#endif /* SRC_COMMON_TYPES_LINK_H_ */ -- 2.7.4 From 5a42ff8c0301cd13463e42860497912e504ce147 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 23 Oct 2014 10:13:55 +0200 Subject: [PATCH 15/16] Add AgentTalker class This class will be used as interface for plugin<->agent communication. Change-Id: Id6d6c439d531a8ff7e0b2b96005c12c5a5ab63b7 --- src/service/CMakeLists.txt | 1 + src/service/agent/AgentTalker.cpp | 52 ++++++++++++++++++++++++++++ src/service/agent/AgentTalker.h | 71 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 src/service/agent/AgentTalker.cpp create mode 100644 src/service/agent/AgentTalker.h diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index c317d8e..d6fd025 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -19,6 +19,7 @@ SET(CYNARA_SERVICE_PATH ${CYNARA_PATH}/service) SET(CYNARA_SOURCES + ${CYNARA_SERVICE_PATH}/agent/AgentTalker.cpp ${CYNARA_SERVICE_PATH}/logic/Logic.cpp ${CYNARA_SERVICE_PATH}/main/Cynara.cpp ${CYNARA_SERVICE_PATH}/main/main.cpp diff --git a/src/service/agent/AgentTalker.cpp b/src/service/agent/AgentTalker.cpp new file mode 100644 index 0000000..45f8a50 --- /dev/null +++ b/src/service/agent/AgentTalker.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/service/agent/AgentTalker.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief Definition of AgentTalker class + */ + +#include +#include +#include +#include +#include + +#include + +#include "AgentTalker.h" + +namespace Cynara { + +void AgentTalker::sendMessage(const AgentResponseType type, const RawBuffer &data) { + ResponseTakerPtr responseTaker = std::make_shared(); + auto context = std::make_shared(responseTaker, m_linkId); + context->returnResponse(context, + std::make_shared(type, data, m_checkId)); +} + +void AgentTalker::send(const PluginData &agentData) { + RawBuffer data(agentData.begin(), agentData.end()); + sendMessage(CYNARA_MSG_TYPE_ACTION, data); +} + +void AgentTalker::cancel(void) { + RawBuffer data; + sendMessage(CYNARA_MSG_TYPE_CANCEL, data); +} + +} // namespace Cynara diff --git a/src/service/agent/AgentTalker.h b/src/service/agent/AgentTalker.h new file mode 100644 index 0000000..fd45af1 --- /dev/null +++ b/src/service/agent/AgentTalker.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/service/agent/AgentTalker.h + * @author Adam Malinowski + * @version 1.0 + * @brief Declaration of AgentTalker class + */ + +#ifndef SRC_SERVICE_AGENT_AGENTTALKER_H_ +#define SRC_SERVICE_AGENT_AGENTTALKER_H_ + +#include + +#include +#include +#include +#include + +#include + +namespace Cynara { + +class AgentTalker { +public: + AgentTalker(const AgentType &agentType, const LinkId &linkId, + const ProtocolFrameSequenceNumber checkId) : m_agentType(agentType), + m_checkId(checkId), m_linkId (linkId) {} + ~AgentTalker() {} + + void send(const PluginData &agentData); + void cancel(void); + + const AgentType &agentType(void) const { + return m_agentType; + } + + const LinkId linkId(void) const { + return m_linkId; + } + + ProtocolFrameSequenceNumber checkId(void) const { + return m_checkId; + } + +private: + const AgentType m_agentType; + const ProtocolFrameSequenceNumber m_checkId; + const LinkId m_linkId; + + void sendMessage(const AgentResponseType type, const RawBuffer &data); +}; + +typedef std::shared_ptr AgentTalkerPtr; + +} // namespace Cynara + +#endif /* SRC_SERVICE_AGENT_AGENTTALKER_H_ */ -- 2.7.4 From 96fc8d9bd0705063691fbe387b8e7ea5c0c0fa5c Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 24 Oct 2014 16:05:58 +0200 Subject: [PATCH 16/16] Add agent manager This commit introduces AgentManager class which will help plugins in communication with agents. Also registering and unregistering agents will be handled by this class. Change-Id: Id3f7e5785223c3b0316f97bc8107805572a0fd10 --- src/service/CMakeLists.txt | 1 + src/service/agent/AgentManager.cpp | 120 +++++++++++++++++++++++++++++++++++++ src/service/agent/AgentManager.h | 72 ++++++++++++++++++++++ src/service/logic/Logic.cpp | 5 +- src/service/logic/Logic.h | 6 ++ src/service/main/Cynara.cpp | 4 ++ src/service/main/Cynara.h | 1 + src/service/main/pointers.h | 3 + 8 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/service/agent/AgentManager.cpp create mode 100644 src/service/agent/AgentManager.h diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index d6fd025..675a866 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -19,6 +19,7 @@ SET(CYNARA_SERVICE_PATH ${CYNARA_PATH}/service) SET(CYNARA_SOURCES + ${CYNARA_SERVICE_PATH}/agent/AgentManager.cpp ${CYNARA_SERVICE_PATH}/agent/AgentTalker.cpp ${CYNARA_SERVICE_PATH}/logic/Logic.cpp ${CYNARA_SERVICE_PATH}/main/Cynara.cpp diff --git a/src/service/agent/AgentManager.cpp b/src/service/agent/AgentManager.cpp new file mode 100644 index 0000000..ee91e64 --- /dev/null +++ b/src/service/agent/AgentManager.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/service/agent/AgentManager.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief Definition of AgentManager class + */ + +#include + +#include +#include +#include + +#include "AgentManager.h" + +namespace Cynara { + +AgentRegisterResponse::Code AgentManager::registerAgent(const AgentType &agentType, + const LinkId &linkId) { + if (m_agents.find(agentType) != m_agents.end()) { + return AgentRegisterResponse::REJECTED; + } + + if (m_agents.insert(std::make_pair(agentType, linkId)).second) { + LOGI("Registered agent: <%s>", agentType.c_str()); + return AgentRegisterResponse::DONE; + } + + LOGE("Error in registering agent: <%s>", agentType.c_str()); + return AgentRegisterResponse::ERROR; +} + +bool AgentManager::getAgentType(const LinkId &linkId, AgentType &agentType) const { + for (const auto &x : m_agents) { + if (x.second == linkId) { + agentType = x.first; + return true; + } + } + return false; +} + +void AgentManager::unregisterAgent(const LinkId &linkId) { + AgentType agentType; + if (!getAgentType(linkId, agentType)) { + LOGD("Trying to unregister not registered agent"); + return; + } + m_agents.erase(agentType); + m_talkers.erase(linkId); + LOGI("Unregistered agent: <%s>", agentType.c_str()); +} + +AgentTalkerPtr AgentManager::createTalker(const AgentType &agentType) { + try { + ProtocolFrameSequenceNumber checkId = generateSequenceNumber(agentType); + const LinkId &linkId = m_agents.at(agentType); + + AgentTalkerPtr talker = std::make_shared(agentType, linkId, checkId); + if (m_talkers[linkId].insert(std::make_pair(checkId, talker)).second) { + LOGD("Created talker for: <%s>:[%" PRIu16 "]", agentType.c_str(), checkId); + return talker; + } + } catch (const std::out_of_range &) { + LOGE("Proper agent not found: <%s>", agentType.c_str()); + } + + return AgentTalkerPtr(); +} + +ProtocolFrameSequenceNumber AgentManager::generateSequenceNumber(const AgentType &agentType UNUSED) +{ + // TODO: implement smart sequence number generation, maybe unique per agent + return m_sequenceNumber++; +} + +AgentTalkerPtr AgentManager::getTalker(const LinkId &linkId, ProtocolFrameSequenceNumber requestId) + const { + const auto talkerMap = m_talkers.find(linkId); + if (talkerMap == m_talkers.end()) { + return AgentTalkerPtr(); + } + + const auto talker = talkerMap->second.find(requestId); + return talker != talkerMap->second.end() ? talker->second : AgentTalkerPtr(); +} + +void AgentManager::removeTalker(const AgentTalkerPtr &agentTalker) { + m_talkers[agentTalker->linkId()].erase(agentTalker->checkId()); +} + +void AgentManager::cleanupAgent(const LinkId &linkId, TalkerCleanupFunction cleanupFunction) { + auto talkerMap = m_talkers.find(linkId); + if (talkerMap == m_talkers.end()) + return; + + if (cleanupFunction) { + for (auto p : talkerMap->second) { + cleanupFunction(p.second); + } + } + unregisterAgent(linkId); +} + +} // namespace Cynara diff --git a/src/service/agent/AgentManager.h b/src/service/agent/AgentManager.h new file mode 100644 index 0000000..38dca72 --- /dev/null +++ b/src/service/agent/AgentManager.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 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. + */ +/** + * @file src/service/agent/AgentManager.h + * @author Adam Malinowski + * @version 1.0 + * @brief Declaration of AgentManager class + */ + +#ifndef SRC_SERVICE_AGENT_AGENTMANAGER_H_ +#define SRC_SERVICE_AGENT_AGENTMANAGER_H_ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace Cynara { + +class AgentManager { +public: + typedef std::map Talkers; + typedef std::function TalkerCleanupFunction; + + AgentManager() : m_sequenceNumber(0) {} + ~AgentManager() {} + + typedef enum { + RR_DONE, + RR_REJECTED, + RR_ERROR + } RegisterResult; + + AgentRegisterResponse::Code registerAgent(const AgentType &agentType, const LinkId &linkId); + + AgentTalkerPtr createTalker(const AgentType &agentType); + void removeTalker(const AgentTalkerPtr &agentTalkerPtr); + AgentTalkerPtr getTalker(const LinkId &linkId, ProtocolFrameSequenceNumber requestId) const; + void cleanupAgent(const LinkId &linkId, TalkerCleanupFunction cleanupFunction); + +private: + std::map m_agents; + std::map m_talkers; + ProtocolFrameSequenceNumber m_sequenceNumber; + + ProtocolFrameSequenceNumber generateSequenceNumber(const AgentType &agentType); + bool getAgentType(const LinkId &linkId, AgentType &agentType) const; + void unregisterAgent(const LinkId &linkId); +}; + +} // namespace Cynara + +#endif /* SRC_SERVICE_AGENT_AGENTMANAGER_H_ */ diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 55f9f63..7227ef9 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -48,6 +48,7 @@ #include #include
+#include #include #include @@ -82,9 +83,9 @@ void Logic::execute(RequestContextPtr context, AdminCheckRequestPtr request) { } void Logic::execute(RequestContextPtr context, AgentRegisterRequestPtr request) { - // MOCKUP + auto result = m_agentManager->registerAgent(request->agentType(), context->responseQueue()); context->returnResponse(context, std::make_shared( - AgentRegisterResponse::DONE, request->sequenceNumber())); + result, request->sequenceNumber())); } void Logic::execute(RequestContextPtr context, CancelRequestPtr request) { diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index 18d8abb..fdf338e 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -38,6 +38,10 @@ public: Logic(); virtual ~Logic(); + void bindAgentManager(const AgentManagerPtr &agentManager) { + m_agentManager = agentManager; + } + void bindPluginManager(PluginManagerPtr pluginManager) { m_pluginManager = pluginManager; } @@ -51,6 +55,7 @@ public: } void unbindAll(void) { + m_agentManager.reset(); m_pluginManager.reset(); m_storage.reset(); m_socketManager.reset(); @@ -68,6 +73,7 @@ public: virtual void contextClosed(RequestContextPtr context); private: + AgentManagerPtr m_agentManager; PluginManagerPtr m_pluginManager; StoragePtr m_storage; SocketManagerPtr m_socketManager; diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index c0f77ef..96443ce 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -47,12 +48,14 @@ Cynara::~Cynara() { } void Cynara::init(void) { + m_agentManager = std::make_shared(); m_logic = std::make_shared(); m_pluginManager = std::make_shared(PathConfig::PluginPath::serviceDir); m_socketManager = std::make_shared(); m_storageBackend = std::make_shared(PathConfig::StoragePath::dbDir); m_storage = std::make_shared(*m_storageBackend); + m_logic->bindAgentManager(m_agentManager); m_logic->bindPluginManager(m_pluginManager); m_logic->bindStorage(m_storage); m_logic->bindSocketManager(m_socketManager); @@ -79,6 +82,7 @@ void Cynara::finalize(void) { m_socketManager->unbindAll(); } + m_agentManager.reset(); m_logic.reset(); m_pluginManager.reset(); m_socketManager.reset(); diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h index 2eb94dc..89bdd76 100644 --- a/src/service/main/Cynara.h +++ b/src/service/main/Cynara.h @@ -37,6 +37,7 @@ public: void finalize(void); private: + AgentManagerPtr m_agentManager; LogicPtr m_logic; PluginManagerPtr m_pluginManager; SocketManagerPtr m_socketManager; diff --git a/src/service/main/pointers.h b/src/service/main/pointers.h index e31eeb8..f32c4ab 100644 --- a/src/service/main/pointers.h +++ b/src/service/main/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class AgentManager; +typedef std::shared_ptr AgentManagerPtr; + class Logic; typedef std::shared_ptr LogicPtr; -- 2.7.4