From 24e4b22d3e1d2bd970f92617e1469a40d34e0c0c Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Thu, 4 Sep 2014 15:50:32 +0200 Subject: [PATCH 01/16] Add async api stub implementation Below are listed asynchronous API functions with its value returned for valid params and enough memory (stub version). - cynara_async_initialize CYNARA_API_SUCCESS - cynara_finish - cynara_async_cache_check CYNARA_API_CACHE_MISS - cynara_async_create_request CYNARA_API_MAX_PENDING_REQUESTS - cynara_async_process CYNARA_API_SUCCESS - cynara_async_cancel_request CYNARA_API_SUCCESS Change-Id: Ic10d04adc5e7d45fa643a1e817db2670c05790cf --- CMakeLists.txt | 1 + packaging/cynara.spec | 56 ++++++-- packaging/libcynara-client-async.manifest | 5 + pkgconfig/CMakeLists.txt | 1 + pkgconfig/cynara-client-async/CMakeLists.txt | 25 ++++ .../cynara-client-async/cynara-client-async.pc.in | 11 ++ src/CMakeLists.txt | 1 + src/client-async/CMakeLists.txt | 49 +++++++ src/client-async/api/ApiInterface.h | 49 +++++++ src/client-async/api/client-async-api.cpp | 146 +++++++++++++++++++++ src/client-async/logic/Logic.cpp | 59 +++++++++ src/client-async/logic/Logic.h | 49 +++++++ src/include/CMakeLists.txt | 1 + src/include/cynara-client-async.h | 2 + 14 files changed, 445 insertions(+), 10 deletions(-) create mode 100644 packaging/libcynara-client-async.manifest create mode 100644 pkgconfig/cynara-client-async/CMakeLists.txt create mode 100644 pkgconfig/cynara-client-async/cynara-client-async.pc.in create mode 100644 src/client-async/CMakeLists.txt create mode 100644 src/client-async/api/ApiInterface.h create mode 100644 src/client-async/api/client-async-api.cpp create mode 100644 src/client-async/logic/Logic.cpp create mode 100644 src/client-async/logic/Logic.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0623e9a..ba5fe97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,7 @@ ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") SET(TARGET_CYNARA "cynara") 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_CYNARA_COMMON "cynara-commons") diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 4d1c960..7508fbf 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -7,15 +7,16 @@ License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1001: cynara.manifest Source1002: libcynara-client.manifest -Source1003: libcynara-admin.manifest -Source1004: cynara-tests.manifest -Source1005: libcynara-client-commons.manifest -Source1006: libcynara-commons.manifest -Source1007: libcynara-creds-commons.manifest -Source1008: libcynara-creds-dbus.manifest -Source1009: libcynara-creds-socket.manifest -Source1010: libcynara-session.manifest -Source1011: libcynara-storage.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 Requires: default-ac-domains Requires(pre): pwdutils Requires(post): smack @@ -42,7 +43,7 @@ BuildRequires: pkgconfig(libunwind) %endif %description -service, client libraries (libcynara-client, libcynara-admin), +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) @@ -64,6 +65,22 @@ Requires: libcynara-client-commons-devel = %{version}-%{release} client library (devel) for checking policies ####################################################### +%package -n libcynara-client-async +Summary: Cynara - asynchronous client library +Requires: cynara = %{version}-%{release} + +%description -n libcynara-client-async +asynchronous client library for checking policies + +%package -n libcynara-client-async-devel +Summary: Cynara - asynchronous client library (devel) +Requires: libcynara-client-async = %{version}-%{release} +Requires: libcynara-client-commons-devel = %{version}-%{release} + +%description -n libcynara-client-async-devel +asynchronous client library (devel) for checking policies + +####################################################### %package -n libcynara-client-commons Summary: Cynara - client commons library Requires: cynara = %{version}-%{release} @@ -214,6 +231,7 @@ cp -a %{SOURCE1008} . cp -a %{SOURCE1009} . cp -a %{SOURCE1010} . cp -a %{SOURCE1011} . +cp -a %{SOURCE1012} . cp -a test/db/db* . %build @@ -290,6 +308,10 @@ fi %postun -n libcynara-client -p /sbin/ldconfig +%post -n libcynara-client-async -p /sbin/ldconfig + +%postun -n libcynara-client-async -p /sbin/ldconfig + %post -n libcynara-client-commons -p /sbin/ldconfig %postun -n libcynara-client-commons -p /sbin/ldconfig @@ -314,6 +336,10 @@ fi %postun -n libcynara-client-devel -p /sbin/ldconfig +%post -n libcynara-client-async-devel -p /sbin/ldconfig + +%postun -n libcynara-client-async-devel -p /sbin/ldconfig + %post -n libcynara-client-commons-devel -p /sbin/ldconfig %postun -n libcynara-client-commons-devel -p /sbin/ldconfig @@ -380,6 +406,16 @@ fi %{_libdir}/pkgconfig/cynara-client.pc %{_libdir}/libcynara-client.so +%files -n libcynara-client-async +%manifest libcynara-client-async.manifest +%license LICENSE +%{_libdir}/libcynara-client-async.so.* + +%files -n libcynara-client-async-devel +%{_includedir}/cynara/cynara-client-async.h +%{_libdir}/pkgconfig/cynara-client-async.pc +%{_libdir}/libcynara-client-async.so + %files -n libcynara-client-commons %manifest libcynara-client-commons.manifest %license LICENSE diff --git a/packaging/libcynara-client-async.manifest b/packaging/libcynara-client-async.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libcynara-client-async.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index 0c11631..9d4600f 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -18,6 +18,7 @@ # ADD_SUBDIRECTORY(cynara-client) +ADD_SUBDIRECTORY(cynara-client-async) ADD_SUBDIRECTORY(cynara-admin) ADD_SUBDIRECTORY(cynara-creds-commons) ADD_SUBDIRECTORY(cynara-creds-dbus) diff --git a/pkgconfig/cynara-client-async/CMakeLists.txt b/pkgconfig/cynara-client-async/CMakeLists.txt new file mode 100644 index 0000000..f827ac4 --- /dev/null +++ b/pkgconfig/cynara-client-async/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 CMakeLists.txt +# @author Marcin Niesluchowski +# + +CONFIGURE_FILE(cynara-client-async.pc.in cynara-client-async.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-client-async/cynara-client-async.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig + ) diff --git a/pkgconfig/cynara-client-async/cynara-client-async.pc.in b/pkgconfig/cynara-client-async/cynara-client-async.pc.in new file mode 100644 index 0000000..cf38a83 --- /dev/null +++ b/pkgconfig/cynara-client-async/cynara-client-async.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: cynara-client-async +Description: cynara-client-async package +Version: @CYNARA_VERSION@ +Requires: +Libs: -L${libdir} -lcynara-client-async +Cflags: -I${includedir}/cynara diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66a1186..fe4d096 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,6 +46,7 @@ INCLUDE_DIRECTORIES( ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(client-async) ADD_SUBDIRECTORY(client-common) ADD_SUBDIRECTORY(admin) ADD_SUBDIRECTORY(storage) diff --git a/src/client-async/CMakeLists.txt b/src/client-async/CMakeLists.txt new file mode 100644 index 0000000..3a4ce35 --- /dev/null +++ b/src/client-async/CMakeLists.txt @@ -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 CMakeLists.txt +# @author Marcin Niesluchowski +# + +SET(LIB_CYNARA_ASYNC_VERSION_MAJOR 0) +SET(LIB_CYNARA_ASYNC_VERSION ${LIB_CYNARA_ASYNC_VERSION_MAJOR}.0.2) + +SET(CYNARA_LIB_CYNARA_ASYNC_PATH ${CYNARA_PATH}/client-async) + +INCLUDE_DIRECTORIES( + ${CYNARA_LIB_CYNARA_ASYNC_PATH} + ${CYNARA_PATH}/client-common + ${CYNARA_PATH}/common + ${CYNARA_PATH}/include + ) + +SET(LIB_CYNARA_ASYNC_SOURCES + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp + ) + +ADD_LIBRARY(${TARGET_LIB_CYNARA_ASYNC} SHARED ${LIB_CYNARA_ASYNC_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_LIB_CYNARA_ASYNC} + PROPERTIES + SOVERSION ${LIB_CYNARA_ASYNC_VERSION_MAJOR} + VERSION ${LIB_CYNARA_ASYNC_VERSION} + ) + +TARGET_LINK_LIBRARIES(${TARGET_LIB_CYNARA_ASYNC} + ${TARGET_CYNARA_COMMON} + ) + +INSTALL(TARGETS ${TARGET_LIB_CYNARA_ASYNC} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/client-async/api/ApiInterface.h b/src/client-async/api/ApiInterface.h new file mode 100644 index 0000000..31478da --- /dev/null +++ b/src/client-async/api/ApiInterface.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/client-async/api/ApiInterface.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains libcynara-client-async API interface definition. + */ + +#ifndef SRC_CLIENT_ASYNC_API_APIINTERFACE_H_ +#define SRC_CLIENT_ASYNC_API_APIINTERFACE_H_ + +#include + +#include + +namespace Cynara { + +class ApiInterface { +public: + ApiInterface() = default; + virtual ~ApiInterface() {}; + + virtual int checkCache(const std::string &client, const std::string &session, + const std::string &user, const std::string &privilege) = 0; + virtual int 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) = 0; + virtual int process(void) = 0; + virtual int cancelRequest(cynara_check_id checkId) = 0; +}; + +} // namespace Cynara + +#endif /* SRC_CLIENT_ASYNC_API_APIINTERFACE_H_ */ diff --git a/src/client-async/api/client-async-api.cpp b/src/client-async/api/client-async-api.cpp new file mode 100644 index 0000000..d350e10 --- /dev/null +++ b/src/client-async/api/client-async-api.cpp @@ -0,0 +1,146 @@ +/* + * 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-async/api/client-async-api.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief Implementation of external libcynara-client-async API + */ + +#include + +#include +#include +#include + +#include +#include +#include + +struct cynara_async { + Cynara::ApiInterface *impl; + + cynara_async(Cynara::ApiInterface *_impl) : impl(_impl) { + } + + ~cynara_async() { + delete impl; + } +}; + +CYNARA_API +int cynara_async_initialize(cynara_async **pp_cynara, + const cynara_async_configuration *p_conf UNUSED, + cynara_status_callback callback, void *user_status_data) { + if (!pp_cynara) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + *pp_cynara = new cynara_async(new Cynara::Logic(callback, user_status_data)); + + init_log(); + + LOGD("Cynara client async initialized"); + + return CYNARA_API_SUCCESS; + }); +} + +CYNARA_API +void cynara_async_finish(cynara_async *p_cynara) { + delete p_cynara; +} + +CYNARA_API +int cynara_async_check_cache(cynara_async *p_cynara, const char *client, const char *client_session, + const char *user, const char *privilege) { + if (!p_cynara || !p_cynara->impl) + return CYNARA_API_INVALID_PARAM; + if (!client || !client_session || !user || !privilege) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + std::string clientStr; + std::string clientSessionStr; + std::string userStr; + std::string privilegeStr; + + try { + clientStr = client; + clientSessionStr = client_session; + userStr = user; + privilegeStr = privilege; + } catch (const std::length_error &e) { + LOGE(e.what()); + return CYNARA_API_INVALID_PARAM; + } + return p_cynara->impl->checkCache(clientStr, clientSessionStr, userStr, privilegeStr); + }); +} + +CYNARA_API +int cynara_async_create_request(cynara_async *p_cynara, const char *client, + const char *client_session, const char *user, const char *privilege, + cynara_check_id *p_check_id, cynara_response_callback callback, + void *user_response_data) { + if (!p_cynara || !p_cynara->impl) + return CYNARA_API_INVALID_PARAM; + if (!client || !client_session || !user || !privilege) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + std::string clientStr; + std::string clientSessionStr; + std::string userStr; + std::string privilegeStr; + + try { + clientStr = client; + clientSessionStr = client_session; + userStr = user; + privilegeStr = privilege; + } catch (const std::length_error &e) { + LOGE(e.what()); + return CYNARA_API_INVALID_PARAM; + } + cynara_check_id checkId; + int ret = p_cynara->impl->createRequest(clientStr, clientSessionStr, userStr, privilegeStr, + checkId, callback, user_response_data); + if (p_check_id && ret == CYNARA_API_SUCCESS) + *p_check_id = checkId; + return ret; + }); +} + +CYNARA_API +int cynara_async_process(cynara_async *p_cynara) { + if (!p_cynara || !p_cynara->impl) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + return p_cynara->impl->process(); + }); +} + +CYNARA_API +int cynara_async_cancel_request(cynara_async *p_cynara, cynara_check_id check_id) { + if (!p_cynara || !p_cynara->impl) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + return p_cynara->impl->cancelRequest(check_id); + }); +} diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp new file mode 100644 index 0000000..f20a216 --- /dev/null +++ b/src/client-async/logic/Logic.cpp @@ -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/client-async/logic/Logic.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains implementation of Logic class - main + * libcynara-client-async class + */ + +#include + +#include "Logic.h" + +namespace Cynara { + +Logic::Logic(cynara_status_callback callback UNUSED, void *userStatusData UNUSED) { + // MOCKUP +} + +int Logic::checkCache(const std::string &client UNUSED, const std::string &session UNUSED, + const std::string &user UNUSED, const std::string &privilege UNUSED) { + // MOCKUP + return CYNARA_API_CACHE_MISS; +} + +int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED, + const std::string &user UNUSED, const std::string &privilege UNUSED, + cynara_check_id &checkId UNUSED, cynara_response_callback callback UNUSED, + void *userResponseData UNUSED) { + // MOCKUP + return CYNARA_API_MAX_PENDING_REQUESTS; +} + + +int Logic::process(void) { + // MOCKUP + return CYNARA_API_SUCCESS; +} + +int Logic::cancelRequest(cynara_check_id checkId UNUSED) { + // MOCKUP + return CYNARA_API_SUCCESS; +} + +} // namespace Cynara diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h new file mode 100644 index 0000000..d245501 --- /dev/null +++ b/src/client-async/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/client-async/logic/Logic.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains declaration of Logic class - main + * libcynara-client-async class + */ + +#ifndef SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ +#define SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ + +#include +#include + +namespace Cynara { + +class Logic : public ApiInterface { +public: + Logic(cynara_status_callback callback, void *userStatusData); + virtual ~Logic() {}; + + virtual int checkCache(const std::string &client, const std::string &session, + const std::string &user, const std::string &privilege); + virtual int 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); + virtual int process(void); + virtual int cancelRequest(cynara_check_id checkId); +}; + +} // namespace Cynara + +#endif /* SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ */ diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index e4c74a4..1be6e10 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin-error.h ${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-error.h ${CYNARA_PATH}/include/cynara-creds-commons.h ${CYNARA_PATH}/include/cynara-creds-dbus.h diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index c824124..1e39d9b 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -27,6 +27,8 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif -- 2.7.4 From 1dcea79f6b7f2880b32091a3f0a035e878fa0e94 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Mon, 15 Sep 2014 11:17:34 +0200 Subject: [PATCH 02/16] Move socket paths to common library Change-Id: I4b5bf9c2bc47aca6f87bb89942a09b2a8ae6e251 --- src/admin/logic/Logic.cpp | 5 ++--- src/client/logic/Logic.cpp | 5 ++--- src/common/CMakeLists.txt | 1 + src/common/sockets/SocketPath.cpp | 32 ++++++++++++++++++++++++++++++ src/common/sockets/SocketPath.h | 37 +++++++++++++++++++++++++++++++++++ src/service/sockets/SocketManager.cpp | 8 ++++---- 6 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 src/common/sockets/SocketPath.cpp create mode 100644 src/common/sockets/SocketPath.h diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 95ececc..89c2d2c 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -38,16 +38,15 @@ #include #include #include +#include #include #include "Logic.h" namespace Cynara { -const std::string adminSocketPath("/run/cynara/cynara-admin.socket"); - Logic::Logic() { - m_socketClient = std::make_shared(adminSocketPath, + m_socketClient = std::make_shared(SocketPath::admin, std::make_shared()); } diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index 2708318..d856042 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -35,20 +35,19 @@ #include #include #include +#include #include namespace Cynara { -const std::string clientSocketPath("/run/cynara/cynara.socket"); - static ProtocolFrameSequenceNumber generateSequenceNumber(void) { static ProtocolFrameSequenceNumber sequenceNumber = 0; return ++sequenceNumber; } Logic::Logic() { - m_socket = std::make_shared(clientSocketPath, std::make_shared()); + m_socket = std::make_shared(SocketPath::client, std::make_shared()); m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 0901962..490a4f3 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -43,6 +43,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/response/ResponseTaker.cpp ${COMMON_PATH}/sockets/Socket.cpp ${COMMON_PATH}/sockets/SocketClient.cpp + ${COMMON_PATH}/sockets/SocketPath.cpp ${COMMON_PATH}/types/PolicyBucket.cpp ${COMMON_PATH}/types/PolicyKey.cpp ${COMMON_PATH}/types/PolicyKeyHelpers.cpp diff --git a/src/common/sockets/SocketPath.cpp b/src/common/sockets/SocketPath.cpp new file mode 100644 index 0000000..c64e2ff --- /dev/null +++ b/src/common/sockets/SocketPath.cpp @@ -0,0 +1,32 @@ +/* + * 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/sockets/SocketPath.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief Source file for common socket paths + */ + +#include "SocketPath.h" + +namespace Cynara { +namespace SocketPath { + +const std::string client("/run/cynara/cynara.socket"); +const std::string admin("/run/cynara/cynara-admin.socket"); + +} // namespace SocketPath +} // namespace Cynara diff --git a/src/common/sockets/SocketPath.h b/src/common/sockets/SocketPath.h new file mode 100644 index 0000000..cca867d --- /dev/null +++ b/src/common/sockets/SocketPath.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/sockets/SocketPath.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief Header for common socket paths + */ + +#ifndef SRC_COMMON_SOCKETS_SOCKETPATH_H_ +#define SRC_COMMON_SOCKETS_SOCKETPATH_H_ + +#include + +namespace Cynara { +namespace SocketPath { + +extern const std::string client; +extern const std::string admin; + +} // namespace SocketPath +} // namespace Cynara + +#endif // SRC_COMMON_SOCKETS_SOCKETPATH_H_ diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index 29bc999..cb3c9b4 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include
@@ -69,14 +70,13 @@ void SocketManager::run(void) { void SocketManager::init(void) { LOGI("SocketManger init start"); - const std::string clientSocketPath("/run/cynara/cynara.socket"); - const std::string adminSocketPath("/run/cynara/cynara-admin.socket"); const mode_t clientSocketUMask(0); const mode_t adminSocketUMask(0077); - createDomainSocket(std::make_shared(), clientSocketPath, clientSocketUMask, + createDomainSocket(std::make_shared(), SocketPath::client, clientSocketUMask, true); - createDomainSocket(std::make_shared(), adminSocketPath, adminSocketUMask, false); + createDomainSocket(std::make_shared(), SocketPath::admin, adminSocketUMask, + false); createSignalSocket(std::make_shared()); LOGI("SocketManger init done"); } -- 2.7.4 From edf3b9e805df58c39137ac1e50dfe17a47f6c844 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Mon, 15 Sep 2014 11:42:42 +0200 Subject: [PATCH 03/16] Add asynchronous socket Change-Id: I1ca062fee144b8244fba88ae3155096df043c61e --- src/admin/logic/Logic.cpp | 67 +++--- src/admin/logic/Logic.h | 1 + src/client-async/CMakeLists.txt | 1 + src/client-async/sockets/SocketClientAsync.cpp | 72 +++++++ src/client-async/sockets/SocketClientAsync.h | 65 ++++++ src/client-common/exceptions/TryCatch.h | 4 + src/client/logic/Logic.cpp | 56 ++--- src/client/logic/Logic.h | 1 + ...nectionErrorException.h => NoMemoryException.h} | 35 ++-- src/common/sockets/Socket.cpp | 231 ++++++++++++--------- src/common/sockets/Socket.h | 81 ++++++-- src/common/sockets/SocketClient.cpp | 31 ++- src/common/sockets/SocketClient.h | 5 +- 13 files changed, 457 insertions(+), 193 deletions(-) create mode 100644 src/client-async/sockets/SocketClientAsync.cpp create mode 100644 src/client-async/sockets/SocketClientAsync.h rename src/common/exceptions/{ServerConnectionErrorException.h => NoMemoryException.h} (52%) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 89c2d2c..6906056 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -25,7 +25,8 @@ #include #include -#include +#include +#include #include #include #include @@ -55,19 +56,30 @@ ProtocolFrameSequenceNumber generateSequenceNumber(void) { return ++sequenceNumber; } +bool Logic::ensureConnection(void) { + return m_socketClient->isConnected() || m_socketClient->connect(); +} + template int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { - ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); - - //Ask cynara service - CodeResponsePtr codeResponse; try { - RequestPtr request = std::make_shared(args..., sequenceNumber); - ResponsePtr response = m_socketClient->askCynaraServer(request); - if (!response) { - LOGW("Disconnected by cynara server."); + if (!ensureConnection()) { + LOGE("Cannot connect to cynara. Service not available."); return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; } + + ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); + + //Ask cynara service + CodeResponsePtr codeResponse; + + RequestPtr request = std::make_shared(args..., sequenceNumber); + ResponsePtr response; + while (!(response = m_socketClient->askCynaraServer(request))) { + if (!m_socketClient->connect()) + return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; + } + codeResponse = std::dynamic_pointer_cast(response); if (!codeResponse) { LOGC("Critical error. Casting Response to CodeResponse failed."); @@ -90,9 +102,6 @@ int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { static_cast(codeResponse->m_code)); return CYNARA_ADMIN_API_UNEXPECTED_CLIENT_ERROR; } - } catch (const ServerConnectionErrorException &ex) { - LOGE("Cynara service not available."); - return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; } catch (const std::bad_alloc &ex) { LOGE("Cynara admin client out of memory."); return CYNARA_ADMIN_API_OUT_OF_MEMORY; @@ -118,19 +127,25 @@ int Logic::removeBucket(const PolicyBucketId &bucket) noexcept { int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result) noexcept { + try { + if (!ensureConnection()) { + LOGE("Cannot connect to cynara. Service not available."); + return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; + } - ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); + ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); + + //Ask cynara service + CheckResponsePtr checkResponse; - //Ask cynara service - CheckResponsePtr checkResponse; - try { RequestPtr request = std::make_shared(key, startBucket, recursive, sequenceNumber); - ResponsePtr response = m_socketClient->askCynaraServer(request); - if (!response) { - LOGW("Disconnected by cynara server."); - return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; + ResponsePtr response; + while (!(response = m_socketClient->askCynaraServer(request))) { + if (!m_socketClient->connect()) + return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; } + checkResponse = std::dynamic_pointer_cast(response); if (!checkResponse) { LOGC("Casting Response to CheckResponse failed."); @@ -140,9 +155,12 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P LOGD("checkResponse: policyType [%" PRIu16 "], metadata <%s>", checkResponse->m_resultRef.policyType(), checkResponse->m_resultRef.metadata().c_str()); - } catch (const ServerConnectionErrorException &ex) { - LOGE("Cynara service not available."); - return CYNARA_ADMIN_API_SERVICE_NOT_AVAILABLE; + + result = checkResponse->m_resultRef; + return CYNARA_ADMIN_API_SUCCESS; + } catch (const UnexpectedErrorException &ex) { + LOGE(ex.what()); + return CYNARA_ADMIN_API_UNEXPECTED_CLIENT_ERROR; } catch (const std::bad_alloc &ex) { LOGE("Cynara admin client out of memory."); return CYNARA_ADMIN_API_OUT_OF_MEMORY; @@ -150,9 +168,6 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P LOGE("Unexpected client error: <%s>", ex.what()); return CYNARA_ADMIN_API_UNEXPECTED_CLIENT_ERROR; } - - result = checkResponse->m_resultRef; - return CYNARA_ADMIN_API_SUCCESS; } } // namespace Cynara diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index 8a274ff..527e992 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -35,6 +35,7 @@ class Logic : public ApiInterface { private: SocketClientPtr m_socketClient; + bool ensureConnection(void); template int askCynaraAndInterpreteCodeResponse(Args... args); diff --git a/src/client-async/CMakeLists.txt b/src/client-async/CMakeLists.txt index 3a4ce35..1326f8d 100644 --- a/src/client-async/CMakeLists.txt +++ b/src/client-async/CMakeLists.txt @@ -31,6 +31,7 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_ASYNC_SOURCES ${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sockets/SocketClientAsync.cpp ) ADD_LIBRARY(${TARGET_LIB_CYNARA_ASYNC} SHARED ${LIB_CYNARA_ASYNC_SOURCES}) diff --git a/src/client-async/sockets/SocketClientAsync.cpp b/src/client-async/sockets/SocketClientAsync.cpp new file mode 100644 index 0000000..e3ffbd4 --- /dev/null +++ b/src/client-async/sockets/SocketClientAsync.cpp @@ -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/client-async/sockets/SocketClientAsync.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains definition of cynara's socket asynchronous + * client + */ + +#include +#include + +#include "SocketClientAsync.h" + +namespace Cynara { + +SocketClientAsync::SocketClientAsync(const std::string &socketPath, ProtocolPtr protocol) + : m_socket(socketPath, 0), m_protocol(protocol) { +} + +Socket::ConnectionStatus SocketClientAsync::connect(void) { + return m_socket.connect(); +} + +Socket::ConnectionStatus SocketClientAsync::completeConnection(void) { + return m_socket.completeConnection(); +} + +int SocketClientAsync::getSockFd(void) { + return m_socket.getSockFd(); +} + +bool SocketClientAsync::isConnected(void) { + return m_socket.isConnected(); +} + +void SocketClientAsync::appendRequest(RequestPtr request) { + RequestContextPtr context = std::make_shared(ResponseTakerPtr(), m_writeQueue); + request->execute(request, m_protocol, context); +} + +bool SocketClientAsync::isDataToSend(void) { + return m_socket.isDataToSend() || !m_writeQueue.empty(); +} + +Socket::SendStatus SocketClientAsync::sendToCynara(void) { + return m_socket.sendToServer(m_writeQueue); +} + +bool SocketClientAsync::receiveFromCynara(void) { + return m_socket.receiveFromServer(m_readQueue); +} + +ResponsePtr SocketClientAsync::getResponse(void) { + return m_protocol->extractResponseFromBuffer(m_readQueue); +} + +} // namespace Cynara diff --git a/src/client-async/sockets/SocketClientAsync.h b/src/client-async/sockets/SocketClientAsync.h new file mode 100644 index 0000000..5fb0543 --- /dev/null +++ b/src/client-async/sockets/SocketClientAsync.h @@ -0,0 +1,65 @@ +/* + * 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-async/sockets/SocketClientAsync.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains declaration of cynara's socket asynchronous + client + */ + +#ifndef SRC_CLIENT_ASYNC_SOCKETS_SOCKETCLIENTASYNC_H_ +#define SRC_CLIENT_ASYNC_SOCKETS_SOCKETCLIENTASYNC_H_ + +#include +#include + +#include +#include +#include +#include +#include + +namespace Cynara { + +class SocketClientAsync; +typedef std::shared_ptr SocketClientAsyncPtr; + +class SocketClientAsync { +public: + SocketClientAsync(const std::string &socketPath, ProtocolPtr protocol); + ~SocketClientAsync() {}; + + Socket::ConnectionStatus connect(void); + Socket::ConnectionStatus completeConnection(void); + int getSockFd(void); + bool isConnected(void); + void appendRequest(RequestPtr request); + bool isDataToSend(void); + Socket::SendStatus sendToCynara(void); + bool receiveFromCynara(void); + ResponsePtr getResponse(void); + +private: + Socket m_socket; + ProtocolPtr m_protocol; + BinaryQueue m_readQueue; + BinaryQueue m_writeQueue; +}; + +} // namespace Cynara + +#endif /* SRC_CLIENT_ASYNC_SOCKETS_SOCKETCLIENTASYNC_H_ */ diff --git a/src/client-common/exceptions/TryCatch.h b/src/client-common/exceptions/TryCatch.h index 8d1fb20..6dc4d0b 100644 --- a/src/client-common/exceptions/TryCatch.h +++ b/src/client-common/exceptions/TryCatch.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -39,6 +40,9 @@ int tryCatch(const std::function &func) { } catch (const std::bad_alloc &e) { LOGE(e.what()); return CYNARA_API_OUT_OF_MEMORY; + } catch (const NoMemoryException &e) { + LOGE(e.what()); + return CYNARA_API_OUT_OF_MEMORY; } catch (const std::exception &e) { LOGE(e.what()); return CYNARA_API_UNKNOWN_ERROR; diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index d856042..f375e9e 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -56,14 +57,12 @@ Logic::Logic() { } int Logic::check(const std::string &client, const ClientSession &session, const std::string &user, - const std::string &privilege) -{ - if (!m_socket->isConnected()){ - onDisconnected(); - } + const std::string &privilege) { + if (!ensureConnection()) + return CYNARA_API_SERVICE_NOT_AVAILABLE; PolicyKey key(client, user, privilege); - auto ret = m_cache->get(session, key); + int ret = m_cache->get(session, key); //Any other situation than cache miss if (ret != CYNARA_API_CACHE_MISS) { return ret; @@ -80,32 +79,39 @@ int Logic::check(const std::string &client, const ClientSession &session, const return m_cache->update(session, key, result); } +bool Logic::ensureConnection(void) { + if (m_socket->isConnected()) + return true; + onDisconnected(); + if (m_socket->connect()) + return true; + LOGW("Cannot connect to cynara. Service not available."); + return false; +} + int Logic::requestResult(const PolicyKey &key, PolicyResult &result) { ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); //Ask cynara service CheckResponsePtr checkResponse; - try { - RequestPtr request = std::make_shared(key, sequenceNumber); - ResponsePtr response = m_socket->askCynaraServer(request); - if (!response) { - LOGW("Disconnected by cynara server."); + RequestPtr request = std::make_shared(key, sequenceNumber); + ResponsePtr response; + while (!(response = m_socket->askCynaraServer(request))) { + onDisconnected(); + if (!m_socket->connect()) return CYNARA_API_SERVICE_NOT_AVAILABLE; - } - checkResponse = std::dynamic_pointer_cast(response); - if (!checkResponse) { - LOGC("Critical error. Casting Response to CheckResponse failed."); - return CYNARA_API_ACCESS_DENIED; - } - - LOGD("checkResponse: policyType = %" PRIu16 ", metadata = %s", - checkResponse->m_resultRef.policyType(), - checkResponse->m_resultRef.metadata().c_str()); - } catch (const ServerConnectionErrorException &ex) { - LOGE("Cynara service not available."); - return CYNARA_API_SERVICE_NOT_AVAILABLE; } + checkResponse = std::dynamic_pointer_cast(response); + if (!checkResponse) { + LOGC("Critical error. Casting Response to CheckResponse failed."); + return CYNARA_API_ACCESS_DENIED; + } + + LOGD("checkResponse: policyType = %" PRIu16 ", metadata = %s", + checkResponse->m_resultRef.policyType(), + checkResponse->m_resultRef.metadata().c_str()); + result = checkResponse->m_resultRef; return CYNARA_API_SUCCESS; } diff --git a/src/client/logic/Logic.h b/src/client/logic/Logic.h index 36076fc..c72309c 100644 --- a/src/client/logic/Logic.h +++ b/src/client/logic/Logic.h @@ -40,6 +40,7 @@ private: PluginCachePtr m_cache; void onDisconnected(void); + bool ensureConnection(void); int requestResult(const PolicyKey &key, PolicyResult &result); public: Logic(); diff --git a/src/common/exceptions/ServerConnectionErrorException.h b/src/common/exceptions/NoMemoryException.h similarity index 52% rename from src/common/exceptions/ServerConnectionErrorException.h rename to src/common/exceptions/NoMemoryException.h index fc550ce..d8a6086 100644 --- a/src/common/exceptions/ServerConnectionErrorException.h +++ b/src/common/exceptions/NoMemoryException.h @@ -14,30 +14,39 @@ * limitations under the License. */ /** - * @file src/common/exceptions/ServerConnectionErrorException.h - * @author Lukasz Wojciechowski + * @file src/common/exceptions/NoMemoryException.h + * @author Marcin Niesluchowski * @version 1.0 - * @brief Implementation of ServerConnectionErrorException + * @brief Implementation of NoMemoryException */ -#ifndef SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_ -#define SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_ +#ifndef SRC_COMMON_EXCEPTIONS_NOMEMORYEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_NOMEMORYEXCEPTION_H_ -#include "Exception.h" +#include +#include -#include +#include "Exception.h" namespace Cynara { -class ServerConnectionErrorException : public Exception { +class NoMemoryException : public Exception { public: - ServerConnectionErrorException() = default; - virtual ~ServerConnectionErrorException() noexcept {}; + NoMemoryException() = delete; + NoMemoryException(const std::string &errorMsg) { + m_whatMessage = "NoMemoryException with message <" + errorMsg + ">"; + } + + virtual ~NoMemoryException() noexcept {}; + virtual const std::string message(void) const { - return "ServerConnectionError"; + return m_whatMessage; } + +private: + std::string m_whatMessage; }; -} /* namespace Cynara */ +} // namespace Cynara -#endif /* SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_ */ +#endif /* SRC_COMMON_EXCEPTIONS_NOMEMORYEXCEPTION_H_ */ diff --git a/src/common/sockets/Socket.cpp b/src/common/sockets/Socket.cpp index e3b91dc..0c33a7e 100644 --- a/src/common/sockets/Socket.cpp +++ b/src/common/sockets/Socket.cpp @@ -31,10 +31,8 @@ #include #include -#include -#include #include -#include +#include #include #include @@ -42,8 +40,9 @@ namespace Cynara { -Socket::Socket(const std::string &socketPath, int timeoutMiliseconds) : m_sock(-1), - m_socketPath(socketPath), m_pollTimeout(timeoutMiliseconds) { +Socket::Socket(const std::string &socketPath, int timeoutMiliseconds) + : m_sock(-1), m_connectionInProgress(false), m_socketPath(socketPath), + m_pollTimeout(timeoutMiliseconds), m_sendBufferPos(0), m_sendBufferEnd(0) { } Socket::~Socket() { @@ -54,6 +53,9 @@ void Socket::close(void) { if (m_sock > -1) ::close(m_sock); m_sock = -1; + m_sendBufferPos = 0; + m_sendBufferEnd = 0; + m_sendQueue.clear(); } bool Socket::waitForSocket(int event) { @@ -62,12 +64,14 @@ bool Socket::waitForSocket(int event) { desc[0].fd = m_sock; desc[0].events = event; - ret = TEMP_FAILURE_RETRY(poll(desc, 1, m_pollTimeout)); + if (event != POLLHUP) + ret = TEMP_FAILURE_RETRY(poll(desc, 1, m_pollTimeout)); + else + ret = TEMP_FAILURE_RETRY(poll(desc, 1, 0)); if (ret == -1) { int err = errno; LOGE("'poll' function error [%d] : <%s>", err, strerror(err)); - close(); throw UnexpectedErrorException(err, strerror(err)); } else if (ret == 0) { LOGD("Poll timeout"); @@ -82,7 +86,6 @@ int Socket::getSocketError(void) { int ret = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &err, &len); if (ret < 0) { int err = errno; - close(); LOGE("'getsockopt' function error [%d] : <%s>", err, strerror(err)); throw UnexpectedErrorException(err, strerror(err)); } @@ -90,26 +93,21 @@ int Socket::getSocketError(void) { } bool Socket::isConnected(void) { + if (m_connectionInProgress) + return true; + if (m_sock < 0) return false; - if (getSocketError() != 0) { - close(); + if (getSocketError() != 0) return false; - } - return true; + return !waitForSocket(POLLHUP); } -bool Socket::connect(void) { - sockaddr_un clientAddr; +void Socket::createSocket(void) { int flags; - if (isConnected()) - return true; - - close(); - m_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (m_sock < 0) { int err = errno; @@ -125,6 +123,10 @@ bool Socket::connect(void) { LOGE("'fcntl' function error [%d] : <%s>", err, strerror(err)); throw UnexpectedErrorException(err, strerror(err)); } +} + +Socket::ConnectionStatus Socket::connectSocket(void) { + sockaddr_un clientAddr; memset(&clientAddr, 0, sizeof(clientAddr)); @@ -145,111 +147,136 @@ bool Socket::connect(void) { SUN_LEN(&clientAddr))); if (retval == -1) { int err = errno; - if (err == EINPROGRESS) { - if (!waitForSocket(POLLOUT)) { - return false; - } - err = getSocketError(); + switch (err) { + case EINPROGRESS: + m_connectionInProgress = true; + return ConnectionStatus::CONNECTION_IN_PROGRESS; + case ECONNREFUSED: + //no one is listening + return ConnectionStatus::CONNECTION_FAILED; + default: + close(); + LOGE("'connect' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); } - if (err == ECONNREFUSED) { - //no one is listening - return false; + } + return ConnectionStatus::CONNECTION_SUCCEEDED; +} + +Socket::SendStatus Socket::sendBuffer(void) { + while (m_sendBufferEnd != m_sendBufferPos) { + if (!waitForSocket(POLLOUT)) { + LOGD("No POLLOUT event"); + return SendStatus::PARTIAL_DATA_SENT; } - close(); - LOGE("'connect' function error [%d] : <%s>", err, strerror(err)); - throw UnexpectedErrorException(err, strerror(err)); + + ssize_t t = TEMP_FAILURE_RETRY(send(m_sock, m_sendBuffer.data() + m_sendBufferPos, + m_sendBufferEnd - m_sendBufferPos, MSG_NOSIGNAL)); + if (t == -1) { + int err = errno; + switch (err) { + case EAGAIN: +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + continue; + case ENOMEM: + throw NoMemoryException("'send' function failed due to ENOMEM"); + case EPIPE: + LOGN("Connection closed by server"); + return SendStatus::CONNECTION_LOST; + default: + LOGE("'send' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + } + m_sendBufferPos += static_cast(t); } + return SendStatus::ALL_DATA_SENT; +} + +Socket::ConnectionStatus Socket::connect(void) { + close(); + + createSocket(); - return isConnected(); + ConnectionStatus status = connectSocket(); + if (status != ConnectionStatus::CONNECTION_SUCCEEDED) + return status; + + return isConnected() ? ConnectionStatus::CONNECTION_SUCCEEDED + : ConnectionStatus::CONNECTION_FAILED; } -bool Socket::sendToServer(BinaryQueue &queue) { - bool retry = false; +Socket::ConnectionStatus Socket::completeConnection(void) { + if (!m_connectionInProgress) + return ConnectionStatus::ALREADY_CONNECTED; - RawBuffer buffer(queue.size()); - queue.flattenConsume(buffer.data(), queue.size()); + if (!waitForSocket(POLLOUT)) + return ConnectionStatus::CONNECTION_IN_PROGRESS; - do { - if (!connect()) { - LOGE("Error connecting to socket"); - throw ServerConnectionErrorException(); - } + m_connectionInProgress = false; + return isConnected() ? ConnectionStatus::CONNECTION_SUCCEEDED + : ConnectionStatus::CONNECTION_FAILED; +} - retry = false; - ssize_t done = 0; - while ((buffer.size() - done) > 0) { - if (! waitForSocket(POLLOUT)) { - LOGE("Error in poll(POLLOUT)"); - throw ServerConnectionErrorException(); - } - ssize_t t = TEMP_FAILURE_RETRY(send(m_sock, buffer.data() + done, - buffer.size() - done, MSG_NOSIGNAL)); - if (t == -1) { - int err = errno; - if (err == EPIPE) { - close(); - LOGN("Connection closed by server. Retrying to connect."); - retry = true; - break; - } - close(); - LOGE("'write' function error [%d] : <%s>", err, strerror(err)); - throw UnexpectedErrorException(err, strerror(err)); - } - done += t; - } - } while (retry); +int Socket::getSockFd(void) { + return m_sock; +} - return true; +bool Socket::isDataToSend(void) { + return !m_sendQueue.empty() || m_sendBufferEnd != 0; } -bool Socket::waitAndReceiveFromServer(BinaryQueue &queue) -{ - if (!waitForSocket(POLLIN)) { - LOGE("Error in poll(POLLIN)"); - throw ServerConnectionErrorException(); - } +Socket::SendStatus Socket::sendToServer(BinaryQueue &queue) { + m_sendQueue.appendMoveFrom(queue); - RawBuffer readBuffer(BUFSIZ); - ssize_t size = TEMP_FAILURE_RETRY(read(m_sock, readBuffer.data(), BUFSIZ)); + SendStatus status = sendBuffer(); + if (status != SendStatus::ALL_DATA_SENT) + return status; - if (size == -1) { - int err = errno; - LOGE("'read' function error [%d] : <%s>", err, strerror(err)); - throw UnexpectedErrorException(err, strerror(err)); - } + if (m_sendQueue.size() > m_sendBuffer.size()) + m_sendBuffer.resize(m_sendQueue.size()); - if (size == 0) { - LOGW("read return 0 / Connection closed by server."); - return false; - } - queue.appendCopy(readBuffer.data(), size); + m_sendBufferEnd = m_sendQueue.size(); + m_sendBufferPos = 0; + + m_sendQueue.flattenConsume(m_sendBuffer.data(), m_sendQueue.size()); - return true; + return sendBuffer(); } -bool Socket::receiveFromServer(BinaryQueue &queue) -{ - RawBuffer readBuffer(BUFSIZ); - ssize_t size = TEMP_FAILURE_RETRY(read(m_sock, readBuffer.data(), BUFSIZ)); +bool Socket::receiveFromServer(BinaryQueue &queue) { + if (!waitForSocket(POLLIN)) { + LOGD("No POLLIN event"); + return true; + } - if (size == -1) { - int err = errno; - if (err == EAGAIN) { - LOGD("is connected, but no data available"); - return true; + RawBuffer buffer(BUFSIZ); + ssize_t size = 0; + while (true) { + size = TEMP_FAILURE_RETRY(read(m_sock, buffer.data(), BUFSIZ)); + if (size == 0) { + LOGW("read return 0 / Connection closed by server."); + return false; } - LOGE("'read' function error [%d] : <%s>", err, strerror(err)); - throw UnexpectedErrorException(err, strerror(err)); - } - if (size == 0) { - LOGW("read return 0 / Connection closed by server."); - return false; - } - queue.appendCopy(readBuffer.data(), size); + if (size == -1) { + int err = errno; + switch (err) { + case EAGAIN: +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return true; + default: + LOGE("'read' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + } - return true; + queue.appendCopy(buffer.data(), static_cast(size)); + } } } // namespace Cynara diff --git a/src/common/sockets/Socket.h b/src/common/sockets/Socket.h index 3c5c37b..0309f41 100644 --- a/src/common/sockets/Socket.h +++ b/src/common/sockets/Socket.h @@ -17,6 +17,7 @@ * @file src/common/sockets/Socket.h * @author Bartlomiej Grzelewski * @author Lukasz Wojciechowski + * @author Marcin Niesluchowski * @version 1.0 * @brief This file contains definition of UNIX client socket class */ @@ -27,16 +28,37 @@ #include #include +#include namespace Cynara { class Socket { +public: + enum class ConnectionStatus { + ALREADY_CONNECTED, + CONNECTION_SUCCEEDED, + CONNECTION_IN_PROGRESS, + CONNECTION_FAILED + }; + + enum class SendStatus { + PARTIAL_DATA_SENT, + ALL_DATA_SENT, + CONNECTION_LOST + }; + private: int m_sock; + bool m_connectionInProgress; std::string m_socketPath; int m_pollTimeout; + RawBuffer m_sendBuffer; + size_t m_sendBufferPos; + size_t m_sendBufferEnd; + BinaryQueue m_sendQueue; + void close(void); //returns true if socket is ready @@ -48,6 +70,21 @@ private: //throws in critical situations int getSocketError(void); + //throws in critical situations + void createSocket(void); + + //returns ConnectionStatus::CONNECTION_SUCCEEDED if connection succeeded + //returns ConnectionStatus::CONNECTION_IN_PROGRESS if connection in progress + //returns ConnectionStatus::CONNECTION_FAILED if connection failed + //throws in critical situations + ConnectionStatus connectSocket(void); + + //returns SendStatus::PARTIAL_DATA_SENT if no data to send is available + //returns SendStatus::ALL_DATA_SENT if no additional data to send + //returns SendStatus::CONNECTION_LOST if connection was lost + //throws in critical situations + SendStatus sendBuffer(void); + public: Socket(const std::string &socketPath, int timeoutMiliseconds = -1); ~Socket(); @@ -56,26 +93,36 @@ public: //throws in critical situations bool isConnected(void); - //returns true if connection succeeded - //returns false if connection was timeout or no one is listening - //throws in critical situations - bool connect(void); - - //returns true if data was successfully send to server - //returns false if connection was lost - //throws ServerConnectionErrorException if cannot connect server (or timeout) - //throws other exceptions in critical situations - bool sendToServer(BinaryQueue &queue); - - //returns true if data was successfully read from server - //returns false if connection was lost - //throws ServerConnectionErrorException if cannot connect server (or timeout) - //throws other exceptions in critical situations - bool waitAndReceiveFromServer(BinaryQueue &queue); + //returns ConnectionStatus::CONNECTION_SUCCEEDED if connection succeeded + //returns ConnectionStatus::CONNECTION_IN_PROGRESS if connection in progress + //returns ConnectionStatus::CONNECTION_FAILED if connection failed + //throws in critical situations + ConnectionStatus connect(void); + + //returns ConnectionStatus::ALREADY_CONNECTED if was already connected + //returns ConnectionStatus::CONNECTION_SUCCEEDED if connection succeeded + //returns ConnectionStatus::CONNECTION_IN_PROGRESS if connection in progress + //returns ConnectionStatus::CONNECTION_FAILED if connection failed + //throws in critical situations + ConnectionStatus completeConnection(void); + + //returns socket descriptor + //returns -1 if socket descriptor no present + int getSockFd(void); + + //returns true There is still data to send + //returns false No data to send + bool isDataToSend(void); + + //returns SendStatus::PARTIAL_DATA_SENT if no all data sent + //returns SendStatus::ALL_DATA_SENT if all data was sent + //returns SendStatus::CONNECTION_LOST if connection was lost + //throws in critical situations + SendStatus sendToServer(BinaryQueue &queue); //returns true if data was successfully read from server //returns false if connection was lost - //throws other exceptions in critical situations + //throws in critical situations bool receiveFromServer(BinaryQueue &queue); }; diff --git a/src/common/sockets/SocketClient.cpp b/src/common/sockets/SocketClient.cpp index a23c438..6db91d6 100644 --- a/src/common/sockets/SocketClient.cpp +++ b/src/common/sockets/SocketClient.cpp @@ -39,21 +39,40 @@ SocketClient::SocketClient(const std::string &socketPath, ProtocolPtr protocol) : m_socket(socketPath), m_protocol(protocol) { } +bool SocketClient::connect(void) { + switch (m_socket.connect()) { + case Socket::ConnectionStatus::CONNECTION_FAILED: + LOGW("Error connecting to Cynara. Service not available."); + return false; + case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: + if (m_socket.completeConnection() == Socket::ConnectionStatus::CONNECTION_FAILED) { + LOGW("Error connecting to Cynara. Service not available."); + return false; + } + default: + return true; + } +} + +bool SocketClient::isConnected(void) { + return m_socket.isConnected(); +} + ResponsePtr SocketClient::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 (!m_socket.sendToServer(m_writeQueue)) { - LOGW("Error sending request to Cynara. Service not available."); + if (m_socket.sendToServer(m_writeQueue) == Socket::SendStatus::CONNECTION_LOST) { + LOGW("Disconnected while sending request to Cynara."); return nullptr; } // receive response from cynara while (true) { - if (!m_socket.waitAndReceiveFromServer(m_readQueue)) { - LOGW("Error receiving response from Cynara. Service not available."); + if (!m_socket.receiveFromServer(m_readQueue)) { + LOGW("Disconnected while receiving response from Cynara."); return nullptr; } ResponsePtr response = m_protocol->extractResponseFromBuffer(m_readQueue); @@ -63,8 +82,4 @@ ResponsePtr SocketClient::askCynaraServer(RequestPtr request) { } } -bool SocketClient::isConnected(void) { - return m_socket.isConnected() && m_socket.receiveFromServer(m_readQueue); -} - } // namespace Cynara diff --git a/src/common/sockets/SocketClient.h b/src/common/sockets/SocketClient.h index a96107e..9f9737f 100644 --- a/src/common/sockets/SocketClient.h +++ b/src/common/sockets/SocketClient.h @@ -48,11 +48,12 @@ public: SocketClient(const std::string &socketPath, ProtocolPtr protocol); virtual ~SocketClient() {}; + bool connect(void); + bool isConnected(void); + //returns pointer to response // or nullptr when connection to cynara service is lost ResponsePtr askCynaraServer(RequestPtr request); - - bool isConnected(void); }; } // namespace Cynara -- 2.7.4 From d4c58c6b56ef4e93f4f052025716b7f80f0306dd Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Mon, 15 Sep 2014 11:54:48 +0200 Subject: [PATCH 04/16] Add connection check cynara_async_check_cache should return CYNARA_API_CACHE_MISS if disconnected. cynara_async_create_request and cynara_async_cancel_request should try reconnecting if disconnected and return CYNARA_API_SERVICE_NOT_AVAILABLE on failure. As cynara_async is connecting asynchronously, it could take connection in progress state which is resolved in cynara_async_process and treated as connected in other functions. As this state exists after reconnecting, there should be no cache entries. cynara_async_process should complete connecting if needed by waiting for write event. If connection fails in cynara_async_process, then CYNARA_API_SERVICE_NOT_AVAILABLE should be returned. Change-Id: I2920f4dbd0bde3e7be74096db33f4ff465bc5028 --- src/client-async/CMakeLists.txt | 3 +- src/client-async/callback/StatusCallback.cpp | 46 ++++++++++++++ src/client-async/callback/StatusCallback.h | 47 +++++++++++++++ src/client-async/logic/Logic.cpp | 90 ++++++++++++++++++++++++++-- src/client-async/logic/Logic.h | 15 ++++- 5 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 src/client-async/callback/StatusCallback.cpp create mode 100644 src/client-async/callback/StatusCallback.h diff --git a/src/client-async/CMakeLists.txt b/src/client-async/CMakeLists.txt index 1326f8d..5b3d404 100644 --- a/src/client-async/CMakeLists.txt +++ b/src/client-async/CMakeLists.txt @@ -30,6 +30,7 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_ASYNC_SOURCES ${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/StatusCallback.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sockets/SocketClientAsync.cpp ) @@ -44,7 +45,7 @@ SET_TARGET_PROPERTIES( ) TARGET_LINK_LIBRARIES(${TARGET_LIB_CYNARA_ASYNC} - ${TARGET_CYNARA_COMMON} + ${TARGET_LIB_CYNARA_COMMON} ) INSTALL(TARGETS ${TARGET_LIB_CYNARA_ASYNC} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/client-async/callback/StatusCallback.cpp b/src/client-async/callback/StatusCallback.cpp new file mode 100644 index 0000000..45da823 --- /dev/null +++ b/src/client-async/callback/StatusCallback.cpp @@ -0,0 +1,46 @@ +/* + * 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-async/callback/StatusCallback.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains definition of StatusCallback class + */ + +#include "StatusCallback.h" + +namespace Cynara { + +StatusCallback::StatusCallback(cynara_status_callback callback, void *userData) + : m_callback(callback), m_userData(userData), m_sockFd(-1), + m_status(cynara_async_status::CYNARA_STATUS_FOR_READ) { +} + +void StatusCallback::onStatusChange(int newFd, cynara_async_status status) { + if (!m_callback) + return; + if (m_status == status && m_sockFd == newFd) + return; + m_callback(m_sockFd, newFd, status, m_userData); + m_sockFd = newFd; + m_status = status; +} + +void StatusCallback::onDisconnected(void) { + onStatusChange(-1, cynara_async_status::CYNARA_STATUS_FOR_READ); +} + +} // namespace Cynara diff --git a/src/client-async/callback/StatusCallback.h b/src/client-async/callback/StatusCallback.h new file mode 100644 index 0000000..468f0a0 --- /dev/null +++ b/src/client-async/callback/StatusCallback.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/client-async/callback/StatusCallback.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains declaration of StatusCallback class + */ + +#ifndef SRC_CLIENT_ASYNC_CALLBACK_STATUSCALLBACK_H_ +#define SRC_CLIENT_ASYNC_CALLBACK_STATUSCALLBACK_H_ + +#include + +namespace Cynara { + +class StatusCallback { +public: + StatusCallback(cynara_status_callback callback, void *userData); + ~StatusCallback() {}; + + void onStatusChange(int newFd, cynara_async_status status); + void onDisconnected(void); + +private: + cynara_status_callback m_callback; + void *m_userData; + int m_sockFd; + cynara_async_status m_status; +}; + +} // namespace Cynara + +#endif /* SRC_CLIENT_ASYNC_CALLBACK_STATUSCALLBACK_H_ */ diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index f20a216..04ae0de 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -21,39 +21,121 @@ * libcynara-client-async class */ +#include + #include +#include +#include +#include +#include +#include +#include #include "Logic.h" namespace Cynara { -Logic::Logic(cynara_status_callback callback UNUSED, void *userStatusData UNUSED) { - // MOCKUP +Logic::Logic(cynara_status_callback callback, void *userStatusData) + : m_statusCallback(callback, userStatusData) { + m_socketClient = std::make_shared( + SocketPath::client, std::make_shared()); +} + +Logic::~Logic() { + onDisconnected(); } int Logic::checkCache(const std::string &client UNUSED, const std::string &session UNUSED, const std::string &user UNUSED, const std::string &privilege UNUSED) { + if (!checkCacheValid()) + return CYNARA_API_CACHE_MISS; + // MOCKUP - return CYNARA_API_CACHE_MISS; + return CYNARA_API_SUCCESS; } int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED, const std::string &user UNUSED, const std::string &privilege UNUSED, cynara_check_id &checkId UNUSED, cynara_response_callback callback UNUSED, void *userResponseData UNUSED) { + if (!ensureConnection()) + return CYNARA_API_SERVICE_NOT_AVAILABLE; + // MOCKUP return CYNARA_API_MAX_PENDING_REQUESTS; } - int Logic::process(void) { + bool completed; + int ret = completeConnection(completed); + if (!completed) + return ret; + // MOCKUP return CYNARA_API_SUCCESS; } int Logic::cancelRequest(cynara_check_id checkId UNUSED) { + if (!ensureConnection()) + return CYNARA_API_SERVICE_NOT_AVAILABLE; + // MOCKUP return CYNARA_API_SUCCESS; } +bool Logic::checkCacheValid(void) { + return m_socketClient->isConnected(); +} + +void Logic::prepareRequestsToSend(void) { + // MOCKUP +} + +cynara_async_status Logic::socketDataStatus(void) { + return m_socketClient->isDataToSend() ? cynara_async_status::CYNARA_STATUS_FOR_RW + : cynara_async_status::CYNARA_STATUS_FOR_READ; +} + +bool Logic::ensureConnection(void) { + if (m_socketClient->isConnected()) + return true; + onDisconnected(); + switch (m_socketClient->connect()) { + case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: + prepareRequestsToSend(); + m_statusCallback.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); + return true; + default: + return false; + } +} + +int Logic::completeConnection(bool &completed) { + switch (m_socketClient->completeConnection()) { + case Socket::ConnectionStatus::ALREADY_CONNECTED: + completed = true; + return CYNARA_API_SUCCESS; + case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: + m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + completed = true; + return CYNARA_API_SUCCESS; + case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: + completed = false; + return CYNARA_API_SUCCESS; + default: + completed = false; + onDisconnected(); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } +} + +void Logic::onDisconnected(void) { + m_statusCallback.onDisconnected(); +} + } // namespace Cynara diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index d245501..bc43ad9 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -25,14 +25,16 @@ #define SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ #include +#include #include +#include namespace Cynara { class Logic : public ApiInterface { public: Logic(cynara_status_callback callback, void *userStatusData); - virtual ~Logic() {}; + virtual ~Logic(); virtual int checkCache(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege); @@ -42,6 +44,17 @@ public: void *userResponseData); virtual int process(void); virtual int cancelRequest(cynara_check_id checkId); + +private: + StatusCallback m_statusCallback; + SocketClientAsyncPtr m_socketClient; + + bool checkCacheValid(void); + void prepareRequestsToSend(void); + cynara_async_status socketDataStatus(void); + bool ensureConnection(void); + int completeConnection(bool &completed); + void onDisconnected(void); }; } // namespace Cynara -- 2.7.4 From 380d6f3411a3032afc425d25e7e3f002d29240a2 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Thu, 18 Sep 2014 14:41:01 +0200 Subject: [PATCH 05/16] Implement cynara_async_check_cache() Change-Id: I1930cdf448dcfdf800d0d5c322ff100baf5a4987 --- src/client-async/logic/Logic.cpp | 15 +++++++++++---- src/client-async/logic/Logic.h | 3 +++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 04ae0de..e1574ce 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -23,10 +23,12 @@ #include +#include #include #include #include #include +#include #include #include #include @@ -39,19 +41,23 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) : m_statusCallback(callback, userStatusData) { m_socketClient = std::make_shared( SocketPath::client, 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); } Logic::~Logic() { onDisconnected(); } -int Logic::checkCache(const std::string &client UNUSED, const std::string &session UNUSED, - const std::string &user UNUSED, const std::string &privilege UNUSED) { +int Logic::checkCache(const std::string &client, const std::string &session, + const std::string &user, const std::string &privilege) { if (!checkCacheValid()) return CYNARA_API_CACHE_MISS; - // MOCKUP - return CYNARA_API_SUCCESS; + return m_cache->get(session, PolicyKey(client, user, privilege)); } int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED, @@ -135,6 +141,7 @@ int Logic::completeConnection(bool &completed) { } void Logic::onDisconnected(void) { + m_cache->clear(); m_statusCallback.onDisconnected(); } diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index bc43ad9..0475b08 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -24,6 +24,8 @@ #ifndef SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ #define SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ +#include + #include #include #include @@ -47,6 +49,7 @@ public: private: StatusCallback m_statusCallback; + PluginCachePtr m_cache; SocketClientAsyncPtr m_socketClient; bool checkCacheValid(void); -- 2.7.4 From 29946e7cef5b2fd04531acdb8ab911eb85e2decf Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Thu, 18 Sep 2014 11:32:15 +0200 Subject: [PATCH 06/16] Add creating, sending and receiving check requests cynara_async_create_request() and cynara_async_process() functions work according to the API header excluding possibility to cancel request. Change-Id: I9818be674d58da5bd431a08b7faf47dfe0157289 --- src/client-async/CMakeLists.txt | 2 + src/client-async/callback/ResponseCallback.cpp | 50 ++++++++++ src/client-async/callback/ResponseCallback.h | 48 ++++++++++ src/client-async/check/CheckData.h | 65 +++++++++++++ src/client-async/logic/Logic.cpp | 122 +++++++++++++++++++++--- src/client-async/logic/Logic.h | 14 +++ src/client-async/sequence/SequenceContainer.cpp | 63 ++++++++++++ src/client-async/sequence/SequenceContainer.h | 48 ++++++++++ 8 files changed, 399 insertions(+), 13 deletions(-) create mode 100644 src/client-async/callback/ResponseCallback.cpp create mode 100644 src/client-async/callback/ResponseCallback.h create mode 100644 src/client-async/check/CheckData.h create mode 100644 src/client-async/sequence/SequenceContainer.cpp create mode 100644 src/client-async/sequence/SequenceContainer.h diff --git a/src/client-async/CMakeLists.txt b/src/client-async/CMakeLists.txt index 5b3d404..a9b9971 100644 --- a/src/client-async/CMakeLists.txt +++ b/src/client-async/CMakeLists.txt @@ -30,8 +30,10 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_ASYNC_SOURCES ${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/ResponseCallback.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/StatusCallback.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp + ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sequence/SequenceContainer.cpp ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sockets/SocketClientAsync.cpp ) diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp new file mode 100644 index 0000000..e4577b3 --- /dev/null +++ b/src/client-async/callback/ResponseCallback.cpp @@ -0,0 +1,50 @@ +/* + * 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-async/callback/ResponseCallback.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains definition of ResponseCallback class + */ + +#include "ResponseCallback.h" + +namespace Cynara { + +ResponseCallback::ResponseCallback(cynara_response_callback callback, void *userData) + : m_callback(callback), m_userData(userData) { +} + +void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const { + if (!m_callback) + return; + m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_ANSWER, response, m_userData); +} + +void ResponseCallback::onFinish(cynara_check_id checkId) const { + if (!m_callback) + return; + m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_FINISH, 0, m_userData); +} + +void ResponseCallback::onDisconnected(cynara_check_id checkId) const { + if (!m_callback) + return; + m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE, 0, + m_userData); +} + +} // namespace Cynara diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h new file mode 100644 index 0000000..47d526a --- /dev/null +++ b/src/client-async/callback/ResponseCallback.h @@ -0,0 +1,48 @@ +/* + * 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-async/callback/ResponseCallback.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains declaration of ResponseCallback class + */ + +#ifndef SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_ +#define SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_ + +#include + +namespace Cynara { + +class ResponseCallback { +public: + ResponseCallback(cynara_response_callback callback, void *userData); + ResponseCallback(const ResponseCallback&) = default; + ~ResponseCallback() {}; + + void onAnswer(cynara_check_id checkId, int response) const; + // MOCKUP + void onFinish(cynara_check_id checkId) const; + void onDisconnected(cynara_check_id checkId) const; + +private: + cynara_response_callback m_callback; + void *m_userData; +}; + +} // namespace Cynara + +#endif /* SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_ */ diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h new file mode 100644 index 0000000..1f8fe90 --- /dev/null +++ b/src/client-async/check/CheckData.h @@ -0,0 +1,65 @@ +/* + * 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-async/check/CheckData.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains CheckData class for storing + * information about asynchronous check request. + */ + +#ifndef SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_ +#define SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_ + +#include +#include + +#include + +#include + +namespace Cynara { + +class CheckData +{ +public: + CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback) + : m_key(key), m_session(session), m_callback(callback) {} + ~CheckData() {} + + const PolicyKey &key(void) const { + return m_key; + } + + const std::string &session(void) const { + return m_session; + } + + const ResponseCallback &callback(void) const { + return m_callback; + } + +private: + PolicyKey m_key; + std::string m_session; + ResponseCallback m_callback; + // MOCKUP +}; + +} // namespace Cynara + +#endif // SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_ + diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index e1574ce..23cd7cc 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -26,10 +26,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -49,7 +52,9 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) } Logic::~Logic() { - onDisconnected(); + for (auto &kv : m_checks) + kv.second.callback().onFinish(kv.first); + m_statusCallback.onDisconnected(); } int Logic::checkCache(const std::string &client, const std::string &session, @@ -60,25 +65,41 @@ int Logic::checkCache(const std::string &client, const std::string &session, return m_cache->get(session, PolicyKey(client, user, privilege)); } -int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED, - const std::string &user UNUSED, const std::string &privilege UNUSED, - cynara_check_id &checkId UNUSED, cynara_response_callback callback UNUSED, - void *userResponseData UNUSED) { +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 (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; - // MOCKUP - return CYNARA_API_MAX_PENDING_REQUESTS; + ProtocolFrameSequenceNumber sequenceNumber; + if (!m_sequenceContainer.get(sequenceNumber)) + return CYNARA_API_MAX_PENDING_REQUESTS; + + PolicyKey key(client, user, privilege); + ResponseCallback responseCallback(callback, userResponseData); + 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); + checkId = static_cast(sequenceNumber); + + return CYNARA_API_SUCCESS; } int Logic::process(void) { bool completed; - int ret = completeConnection(completed); - if (!completed) - return ret; - - // MOCKUP - return CYNARA_API_SUCCESS; + while (true) { + int ret = completeConnection(completed); + if (!completed) + return ret; + if (processOut() && processIn()) + return CYNARA_API_SUCCESS; + onDisconnected(); + if (!connect()) + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } } int Logic::cancelRequest(cynara_check_id checkId UNUSED) { @@ -94,7 +115,67 @@ bool Logic::checkCacheValid(void) { } void Logic::prepareRequestsToSend(void) { + for (auto &kv : m_checks) { + // MOCKUP + m_socketClient->appendRequest(std::make_shared(kv.second.key(), kv.first)); + } +} + +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); + case Socket::SendStatus::PARTIAL_DATA_SENT: + return true; + default: + return false; + } +} + +void Logic::processCheckResponse(CheckResponsePtr checkResponse) { + LOGD("checkResponse: policyType = [%" PRIu16 "], metadata = <%s>", + checkResponse->m_resultRef.policyType(), + checkResponse->m_resultRef.metadata().c_str()); + + auto it = m_checks.find(checkResponse->sequenceNumber()); + if (it == m_checks.end()) { + LOGC("Critical error. Unknown response received: sequenceNumber = [%" PRIu16 "]", + checkResponse->sequenceNumber()); + throw UnexpectedErrorException("Unexpected response from cynara service"); + } + int result = m_cache->update(it->second.session(), it->second.key(), + checkResponse->m_resultRef); // MOCKUP + it->second.callback().onAnswer(static_cast(it->first), result); + m_sequenceContainer.release(it->first); + m_checks.erase(it); +} + +void Logic::processResponses(void) { + ResponsePtr response; + CheckResponsePtr checkResponse; + while (true) { + response = m_socketClient->getResponse(); + if (!response) + break; + + checkResponse = std::dynamic_pointer_cast(response); + if (checkResponse) { + processCheckResponse(checkResponse); + continue; + } + // MOCKUP + LOGC("Critical error. Casting Response to CheckResponse failed."); + throw UnexpectedErrorException("Unexpected response from cynara service"); + } +} + +bool Logic::processIn(void) { + if (!m_socketClient->receiveFromCynara()) + return false; + processResponses(); + return true; } cynara_async_status Logic::socketDataStatus(void) { @@ -106,6 +187,11 @@ bool Logic::ensureConnection(void) { if (m_socketClient->isConnected()) return true; onDisconnected(); + + return connect(); +} + +bool Logic::connect(void) { switch (m_socketClient->connect()) { case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: prepareRequestsToSend(); @@ -117,6 +203,7 @@ bool Logic::ensureConnection(void) { cynara_async_status::CYNARA_STATUS_FOR_RW); return true; default: + onServiceNotAvailable(); return false; } } @@ -136,10 +223,19 @@ int Logic::completeConnection(bool &completed) { default: completed = false; onDisconnected(); + onServiceNotAvailable(); return CYNARA_API_SERVICE_NOT_AVAILABLE; } } +void Logic::onServiceNotAvailable(void) +{ + for (auto &kv : m_checks) + kv.second.callback().onDisconnected(kv.first); + m_checks.clear(); + m_sequenceContainer.clear(); +} + void Logic::onDisconnected(void) { m_cache->clear(); m_statusCallback.onDisconnected(); diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 0475b08..53cfba9 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -25,10 +25,13 @@ #define SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_ #include +#include #include #include +#include #include +#include #include namespace Cynara { @@ -48,15 +51,26 @@ public: virtual int cancelRequest(cynara_check_id checkId); private: + typedef std::map CheckMap; + typedef std::pair CheckPair; + StatusCallback m_statusCallback; PluginCachePtr m_cache; SocketClientAsyncPtr m_socketClient; + CheckMap m_checks; + SequenceContainer m_sequenceContainer; bool checkCacheValid(void); void prepareRequestsToSend(void); cynara_async_status socketDataStatus(void); + bool processOut(void); + void processCheckResponse(CheckResponsePtr checkResponse); + void processResponses(void); + bool processIn(void); bool ensureConnection(void); + bool connect(void); int completeConnection(bool &completed); + void onServiceNotAvailable(void); void onDisconnected(void); }; diff --git a/src/client-async/sequence/SequenceContainer.cpp b/src/client-async/sequence/SequenceContainer.cpp new file mode 100644 index 0000000..95b9318 --- /dev/null +++ b/src/client-async/sequence/SequenceContainer.cpp @@ -0,0 +1,63 @@ +/* + * 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-async/sequence/SequenceContainer.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains definition of SequenceContainer class for + * storing check requests identifiers in libcynara-client-async + */ + +#include +#include +#include +#include + +#include "SequenceContainer.h" + +namespace Cynara { + +SequenceContainer::SequenceContainer() + : m_sequenceVector(((static_cast(UINT16_MAX) + 1) / CHAR_BIT) / sizeof(int), -1) { +} + +bool SequenceContainer::get(ProtocolFrameSequenceNumber &sequenceNumber) { + for (size_t index = 0; index < m_sequenceVector.size(); ++index) { + int pos = ffs(m_sequenceVector[index]); + if (pos != 0) { + sequenceNumber = static_cast(index * sizeof(int) * CHAR_BIT - 1 + pos); + m_sequenceVector[index] ^= 1 << (pos - 1); + return true; + } + } + return false; +} + +bool SequenceContainer::release(ProtocolFrameSequenceNumber sequenceNumber) { + size_t index = static_cast(sequenceNumber) / (CHAR_BIT * sizeof(int)); + int pos = static_cast(sequenceNumber) % (CHAR_BIT * sizeof(int)); + int i = m_sequenceVector[index] | 1 << pos; + if (i == m_sequenceVector[index]) + return false; + m_sequenceVector[index] = i; + return true; +} + +void SequenceContainer::clear(void) { + memset(m_sequenceVector.data(), -1, m_sequenceVector.size() * sizeof(int)); +} + +} // namespace Cynara diff --git a/src/client-async/sequence/SequenceContainer.h b/src/client-async/sequence/SequenceContainer.h new file mode 100644 index 0000000..c8748e6 --- /dev/null +++ b/src/client-async/sequence/SequenceContainer.h @@ -0,0 +1,48 @@ +/* + * 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-async/sequence/SequenceContainer.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file contains declaration of SequenceContainer class for + * storing check requests identifiers in libcynara-client-async + */ + +#ifndef SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_ +#define SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_ + +#include + +#include + +namespace Cynara { + +class SequenceContainer { +public: + SequenceContainer(); + ~SequenceContainer() {} + + bool get(ProtocolFrameSequenceNumber &sequenceNumber); + bool release(ProtocolFrameSequenceNumber sequenceNumber); + void clear(void); + +private: + std::vector m_sequenceVector; +}; + +} // namespace Cynara + +#endif // SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_ -- 2.7.4 From 27541d0fdb1e97ba59e4a08b8c710af33fe64af9 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Wed, 24 Sep 2014 14:14:07 +0200 Subject: [PATCH 07/16] Implement cynara_async_cancel_request() Change-Id: I028d6a2941dc68359590263cda9e5bff2b839317 --- src/client-async/callback/ResponseCallback.cpp | 6 ++ src/client-async/callback/ResponseCallback.h | 2 +- src/client-async/check/CheckData.h | 12 +++- src/client-async/logic/Logic.cpp | 80 ++++++++++++++++++++------ src/client-async/logic/Logic.h | 1 + src/common/CMakeLists.txt | 2 + src/common/protocol/ProtocolClient.cpp | 37 ++++++++++++ src/common/protocol/ProtocolClient.h | 6 ++ src/common/protocol/ProtocolOpCode.h | 4 +- src/common/request/CancelRequest.cpp | 34 +++++++++++ src/common/request/CancelRequest.h | 44 ++++++++++++++ src/common/request/RequestTaker.cpp | 4 ++ src/common/request/RequestTaker.h | 1 + src/common/request/pointers.h | 3 + src/common/response/CancelResponse.cpp | 34 +++++++++++ src/common/response/CancelResponse.h | 44 ++++++++++++++ src/common/response/ResponseTaker.cpp | 4 ++ src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 + src/service/logic/Logic.cpp | 7 +++ src/service/logic/Logic.h | 1 + 21 files changed, 307 insertions(+), 23 deletions(-) create mode 100644 src/common/request/CancelRequest.cpp create mode 100644 src/common/request/CancelRequest.h create mode 100644 src/common/response/CancelResponse.cpp create mode 100644 src/common/response/CancelResponse.h diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp index e4577b3..9307195 100644 --- a/src/client-async/callback/ResponseCallback.cpp +++ b/src/client-async/callback/ResponseCallback.cpp @@ -34,6 +34,12 @@ void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const { m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_ANSWER, response, m_userData); } +void ResponseCallback::onCancel(cynara_check_id checkId) const { + if (!m_callback) + return; + m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_CANCEL, 0, m_userData); +} + void ResponseCallback::onFinish(cynara_check_id checkId) const { if (!m_callback) return; diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h index 47d526a..925d7f4 100644 --- a/src/client-async/callback/ResponseCallback.h +++ b/src/client-async/callback/ResponseCallback.h @@ -34,7 +34,7 @@ public: ~ResponseCallback() {}; void onAnswer(cynara_check_id checkId, int response) const; - // MOCKUP + void onCancel(cynara_check_id checkId) const; void onFinish(cynara_check_id checkId) const; void onDisconnected(cynara_check_id checkId) const; diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h index 1f8fe90..a25abb3 100644 --- a/src/client-async/check/CheckData.h +++ b/src/client-async/check/CheckData.h @@ -37,7 +37,7 @@ class CheckData { public: CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback) - : m_key(key), m_session(session), m_callback(callback) {} + : m_key(key), m_session(session), m_callback(callback), m_cancelled(false) {} ~CheckData() {} const PolicyKey &key(void) const { @@ -52,11 +52,19 @@ public: return m_callback; } + bool cancelled(void) const { + return m_cancelled; + } + + void cancel(void) { + m_cancelled = true; + } + private: PolicyKey m_key; std::string m_session; ResponseCallback m_callback; - // MOCKUP + bool m_cancelled; }; } // namespace Cynara diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 23cd7cc..3a92b2c 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -52,8 +54,10 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) } Logic::~Logic() { - for (auto &kv : m_checks) - kv.second.callback().onFinish(kv.first); + for (auto &kv : m_checks) { + if (!kv.second.cancelled()) + kv.second.callback().onFinish(kv.first); + } m_statusCallback.onDisconnected(); } @@ -102,11 +106,21 @@ int Logic::process(void) { } } -int Logic::cancelRequest(cynara_check_id checkId UNUSED) { +int Logic::cancelRequest(cynara_check_id checkId) { if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; - // MOCKUP + auto it = m_checks.find(checkId); + if (it == m_checks.end() || it->second.cancelled()) + return CYNARA_API_SUCCESS; + + m_socketClient->appendRequest(std::make_shared(it->first)); + + it->second.cancel(); + it->second.callback().onCancel(it->first); + m_statusCallback.onStatusChange(m_socketClient->getSockFd(), + cynara_async_status::CYNARA_STATUS_FOR_RW); + return CYNARA_API_SUCCESS; } @@ -115,9 +129,14 @@ bool Logic::checkCacheValid(void) { } void Logic::prepareRequestsToSend(void) { - for (auto &kv : m_checks) { - // MOCKUP - m_socketClient->appendRequest(std::make_shared(kv.second.key(), kv.first)); + for (auto it = m_checks.begin(); it != m_checks.end();) { + if (it->second.cancelled()) { + m_sequenceContainer.release(it->first); + it = m_checks.erase(it); + } else { + m_socketClient->appendRequest(std::make_shared(it->second.key(), it->first)); + ++it; + } } } @@ -140,14 +159,32 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { auto it = m_checks.find(checkResponse->sequenceNumber()); if (it == m_checks.end()) { - LOGC("Critical error. Unknown response received: sequenceNumber = [%" PRIu16 "]", + LOGC("Critical error. Unknown checkResponse received: sequenceNumber = [%" PRIu16 "]", checkResponse->sequenceNumber()); throw UnexpectedErrorException("Unexpected response from cynara service"); } int result = m_cache->update(it->second.session(), it->second.key(), checkResponse->m_resultRef); - // MOCKUP - it->second.callback().onAnswer(static_cast(it->first), result); + if (!it->second.cancelled()) + it->second.callback().onAnswer(static_cast(it->first), result); + m_sequenceContainer.release(it->first); + m_checks.erase(it); +} + +void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { + LOGD("cancelResponse"); + + auto it = m_checks.find(cancelResponse->sequenceNumber()); + if (it == m_checks.end()) { + LOGC("Critical error. Unknown cancelResponse received: sequenceNumber = [%" PRIu16 "]", + cancelResponse->sequenceNumber()); + throw UnexpectedErrorException("Unexpected response from cynara service"); + } + if (!it->second.cancelled()) { + LOGC("Critical error. CancelRequest not sent: sequenceNumber = [%" PRIu16 "]", + cancelResponse->sequenceNumber()); + throw UnexpectedErrorException("Unexpected response from cynara service"); + } m_sequenceContainer.release(it->first); m_checks.erase(it); } @@ -155,18 +192,21 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { void Logic::processResponses(void) { ResponsePtr response; CheckResponsePtr checkResponse; - while (true) { - response = m_socketClient->getResponse(); - if (!response) - break; - + CancelResponsePtr cancelResponse; + while (response = m_socketClient->getResponse()) { checkResponse = std::dynamic_pointer_cast(response); if (checkResponse) { processCheckResponse(checkResponse); continue; } - // MOCKUP - LOGC("Critical error. Casting Response to CheckResponse failed."); + + cancelResponse = std::dynamic_pointer_cast(response); + if (cancelResponse) { + processCancelResponse(cancelResponse); + continue; + } + + LOGC("Critical error. Casting Response to known response failed."); throw UnexpectedErrorException("Unexpected response from cynara service"); } } @@ -230,8 +270,10 @@ int Logic::completeConnection(bool &completed) { void Logic::onServiceNotAvailable(void) { - for (auto &kv : m_checks) - kv.second.callback().onDisconnected(kv.first); + for (auto &kv : m_checks) { + if (!kv.second.cancelled()) + kv.second.callback().onDisconnected(kv.first); + } m_checks.clear(); m_sequenceContainer.clear(); } diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 53cfba9..0bca98e 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -65,6 +65,7 @@ private: cynara_async_status socketDataStatus(void); bool processOut(void); void processCheckResponse(CheckResponsePtr checkResponse); + void processCancelResponse(CancelResponsePtr cancelResponse); void processResponses(void); bool processIn(void); bool ensureConnection(void); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 490a4f3..d52ddd5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -32,12 +32,14 @@ SET(COMMON_SOURCES ${COMMON_PATH}/protocol/ProtocolSerialization.cpp ${COMMON_PATH}/protocol/ProtocolSignal.cpp ${COMMON_PATH}/request/AdminCheckRequest.cpp + ${COMMON_PATH}/request/CancelRequest.cpp ${COMMON_PATH}/request/CheckRequest.cpp ${COMMON_PATH}/request/InsertOrUpdateBucketRequest.cpp ${COMMON_PATH}/request/RemoveBucketRequest.cpp ${COMMON_PATH}/request/RequestTaker.cpp ${COMMON_PATH}/request/SetPoliciesRequest.cpp ${COMMON_PATH}/request/SignalRequest.cpp + ${COMMON_PATH}/response/CancelResponse.cpp ${COMMON_PATH}/response/CheckResponse.cpp ${COMMON_PATH}/response/CodeResponse.cpp ${COMMON_PATH}/response/ResponseTaker.cpp diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp index 5101900..94811dd 100644 --- a/src/common/protocol/ProtocolClient.cpp +++ b/src/common/protocol/ProtocolClient.cpp @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -52,6 +54,11 @@ ProtocolPtr ProtocolClient::clone(void) { return std::make_shared(); } +RequestPtr ProtocolClient::deserializeCancelRequest(ProtocolFrameHeader &frame) { + LOGD("Deserialized CancelRequest"); + return std::make_shared(frame.sequenceNumber()); +} + RequestPtr ProtocolClient::deserializeCheckRequest(ProtocolFrameHeader &frame) { std::string clientId, userId, privilegeId; @@ -79,6 +86,8 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { switch (opCode) { case OpCheckPolicyRequest: return deserializeCheckRequest(m_frameHeader); + case OpCancelRequest: + return deserializeCancelRequest(m_frameHeader); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; @@ -88,6 +97,11 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { return nullptr; } +ResponsePtr ProtocolClient::deserializeCancelResponse(ProtocolFrameHeader &frame) { + LOGD("Deserialized CancelResponse"); + return std::make_shared(frame.sequenceNumber()); +} + ResponsePtr ProtocolClient::deserializeCheckResponse(ProtocolFrameHeader &frame) { PolicyType result; PolicyResult::PolicyMetadata additionalInfo; @@ -115,6 +129,8 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) switch (opCode) { case OpCheckPolicyResponse: return deserializeCheckResponse(m_frameHeader); + case OpCancelResponse: + return deserializeCancelResponse(m_frameHeader); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; @@ -124,6 +140,16 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) return nullptr; } +void ProtocolClient::execute(RequestContextPtr context, CancelRequestPtr request) { + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + LOGD("Serializing CancelRequest op [%" PRIu8 "]", OpCancelRequest); + + ProtocolSerialization::serialize(*frame, OpCancelRequest); + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); +} + void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) { ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); @@ -139,6 +165,17 @@ void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } +void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr response) { + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + response->sequenceNumber()); + + LOGD("Serializing CancelResponse: op [%" PRIu8 "]", OpCancelResponse); + + ProtocolSerialization::serialize(*frame, OpCancelResponse); + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); +} + void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) { ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( response->sequenceNumber()); diff --git a/src/common/protocol/ProtocolClient.h b/src/common/protocol/ProtocolClient.h index 9493a88..1bb1b6a 100644 --- a/src/common/protocol/ProtocolClient.h +++ b/src/common/protocol/ProtocolClient.h @@ -41,11 +41,17 @@ public: virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue); virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue); + virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); + + virtual void execute(RequestContextPtr context, CancelResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); private: + RequestPtr deserializeCancelRequest(ProtocolFrameHeader &frame); RequestPtr deserializeCheckRequest(ProtocolFrameHeader &frame); + + ResponsePtr deserializeCancelResponse(ProtocolFrameHeader &frame); ResponsePtr deserializeCheckResponse(ProtocolFrameHeader &frame); }; diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 7319ad3..2b4171c 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -33,8 +33,10 @@ enum ProtocolOpCode : uint8_t { /** Client operations */ OpCheckPolicyRequest = 0, OpCheckPolicyResponse, + OpCancelRequest, + OpCancelResponse, - /** Opcodes 2 - 19 are reserved for future use */ + /** Opcodes 4 - 19 are reserved for future use */ /** Admin operations */ OpInsertOrUpdateBucket = 20, diff --git a/src/common/request/CancelRequest.cpp b/src/common/request/CancelRequest.cpp new file mode 100644 index 0000000..d7a5ffa --- /dev/null +++ b/src/common/request/CancelRequest.cpp @@ -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/request/CancelRequest.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file implements cancel request class + */ + +#include + +#include "CancelRequest.h" + +namespace Cynara { + +void CancelRequest::execute(RequestPtr self, RequestTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/CancelRequest.h b/src/common/request/CancelRequest.h new file mode 100644 index 0000000..a6192b8 --- /dev/null +++ b/src/common/request/CancelRequest.h @@ -0,0 +1,44 @@ +/* + * 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/CancelRequest.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file defines cancel request class + */ + +#ifndef SRC_COMMON_REQUEST_CANCELREQUEST_H_ +#define SRC_COMMON_REQUEST_CANCELREQUEST_H_ + +#include +#include +#include + +namespace Cynara { + +class CancelRequest : public Request { +public: + CancelRequest(ProtocolFrameSequenceNumber sequenceNumber) : Request(sequenceNumber) { + } + + virtual ~CancelRequest() {}; + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_CANCELREQUEST_H_ */ diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index d645aee..c87a9a4 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -33,6 +33,10 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, AdminCheckRequestPt throw NotImplementedException(); } +void RequestTaker::execute(RequestContextPtr context UNUSED, CancelRequestPtr request UNUSED) { + throw NotImplementedException(); +} + void RequestTaker::execute(RequestContextPtr context UNUSED, CheckRequestPtr request UNUSED) { throw NotImplementedException(); } diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index 6f1f112..b1d3466 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -33,6 +33,7 @@ public: virtual ~RequestTaker() {}; virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); + virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index 5800321..5c90004 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 CancelRequest; +typedef std::shared_ptr CancelRequestPtr; + class CheckRequest; typedef std::shared_ptr CheckRequestPtr; diff --git a/src/common/response/CancelResponse.cpp b/src/common/response/CancelResponse.cpp new file mode 100644 index 0000000..69211e7 --- /dev/null +++ b/src/common/response/CancelResponse.cpp @@ -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/response/CancelResponse.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file implements cancel response class + */ + +#include + +#include "CancelResponse.h" + +namespace Cynara { + +void CancelResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/CancelResponse.h b/src/common/response/CancelResponse.h new file mode 100644 index 0000000..657ab2c --- /dev/null +++ b/src/common/response/CancelResponse.h @@ -0,0 +1,44 @@ +/* + * 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/CancelResponse.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief This file defines response class for cancel response + */ + +#ifndef SRC_COMMON_RESPONSE_CANCELRESPONSE_H_ +#define SRC_COMMON_RESPONSE_CANCELRESPONSE_H_ + +#include +#include +#include + +namespace Cynara { + +class CancelResponse : public Response { +public: + CancelResponse(ProtocolFrameSequenceNumber sequenceNumber) : Response(sequenceNumber) { + } + + virtual ~CancelResponse() {}; + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, RequestContextPtr context) const; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_CANCELRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index 7da0dfb..3f558c4 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, CancelResponsePtr response UNUSED) { + throw NotImplementedException(); +} + void ResponseTaker::execute(RequestContextPtr context UNUSED, CheckResponsePtr response UNUSED) { throw NotImplementedException(); } diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 41425d8..0afdb65 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, 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 088c533..4e9b8fc 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class CancelResponse; +typedef std::shared_ptr CancelResponsePtr; + class CheckResponse; typedef std::shared_ptr CheckResponsePtr; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index c25487e..d05f512 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -30,12 +30,14 @@ #include
#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -70,6 +72,11 @@ void Logic::execute(RequestContextPtr context, AdminCheckRequestPtr request) { request->sequenceNumber())); } +void Logic::execute(RequestContextPtr context, CancelRequestPtr request) { + // MOCKUP + context->returnResponse(context, std::make_shared(request->sequenceNumber())); +} + void Logic::execute(RequestContextPtr context, CheckRequestPtr request) { PolicyResult result(PredefinedPolicyType::DENY); if (check(context, request->key(), result)) { diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index 84af6ff..28fdeea 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -51,6 +51,7 @@ public: } virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); + virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); -- 2.7.4 From b13293789e389806a41f15b74ff62a82675d902e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Mon, 6 Oct 2014 17:31:59 +0200 Subject: [PATCH 08/16] Improving creation of user 'cynara' MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit To improve the creation of the user cynara, the home directory is now set to /var/lib/empty, the shell is set to /sbin/nologin, the main group is set to cynara. Change-Id: I4582caa9f9a61cd8c52d0a6718f504903cdee479 Signed-off-by: José Bollo --- packaging/cynara.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 7508fbf..c25347f 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -273,7 +273,7 @@ fi id -u %{user_name} > /dev/null 2>&1 if [ $? -eq 1 ]; then - useradd %{user_name} -r > /dev/null 2>&1 + useradd -d /var/lib/empty -s /sbin/nologin -r -g %{group_name} %{user_name} > /dev/null 2>&1 fi %post -- 2.7.4 From 4fc95e366db1631e175bf8955fd3e72e610a4d07 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 12 Sep 2014 15:45:36 +0200 Subject: [PATCH 09/16] Redo client plugins Let plugin make decision based on last and current client session. Plugin can change PluginResult. Change-Id: Ia985feaf1d60a8c1ebf858ba0d4e0d6f2cc6fa40 --- src/client-common/cache/CapacityCache.cpp | 49 ++++++++++++++-------------- src/client-common/cache/CapacityCache.h | 5 ++- src/client-common/plugins/NaiveInterpreter.h | 8 +++-- src/client-common/plugins/PluginInterface.h | 10 +++--- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index c4cf680..04f1cb5 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -30,13 +30,6 @@ namespace Cynara { int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { - //This can be very time heavy. This part is welcomed to be optimized. - if (session != m_session) { - LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str()); - clear(); - m_session = session; - return CYNARA_API_CACHE_MISS; - } auto resultIt = m_keyValue.find(keyToString(key)); //Do we have entry in cache? if (resultIt == m_keyValue.end()) { @@ -51,23 +44,33 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { key.user().toString().c_str(), key.privilege().toString().c_str()); - auto pluginIt = m_plugins.find(resultIt->second.first.policyType()); + auto &cachedValue = resultIt->second; + auto &policyResult = std::get<0>(cachedValue); + + auto pluginIt = m_plugins.find(policyResult.policyType()); if (pluginIt == m_plugins.end()) { LOGE("No plugin registered for given PolicyType : %" PRIu16, - resultIt->second.first.policyType()); + policyResult.policyType()); return CYNARA_API_ACCESS_DENIED; } //Is it still usable? InterpreterInterfacePtr plugin = pluginIt->second; - if (plugin->isUsable(resultIt->second.first)) { + auto &prevSession = std::get<1>(cachedValue); + auto usageIt = std::get<2>(cachedValue); + bool updateSession = false; + if (plugin->isUsable(session, prevSession, updateSession, policyResult)) { LOGD("Entry usable."); - m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, resultIt->second.second); - return plugin->toResult(resultIt->second.first); + m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, usageIt); + + if (updateSession) { + prevSession = session; + } + + return plugin->toResult(session, policyResult); } //Remove unusable entry LOGD("Entry not usable"); - auto usageIt = resultIt->second.second; m_keyUsage.erase(usageIt); m_keyValue.erase(resultIt); return CYNARA_API_CACHE_MISS; @@ -77,7 +80,6 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { void CapacityCache::clear(void) { m_keyUsage.clear(); m_keyValue.clear(); - m_session.clear(); } std::string CapacityCache::keyToString(const PolicyKey &key) { @@ -103,12 +105,6 @@ void CapacityCache::evict(void) { int CapacityCache::update(const ClientSession &session, const PolicyKey &key, const PolicyResult &result) { - //This can be very time heavy. This part is welcomed to be optimized. - if (session != m_session) { - LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str()); - clear(); - m_session = session; - } auto pluginIt = m_plugins.find(result.policyType()); @@ -120,18 +116,21 @@ int CapacityCache::update(const ClientSession &session, } auto plugin = pluginIt->second; - if (m_capacity != 0) { - if (plugin->isCacheable(result)) { + PolicyResult storedResult = result; + + if (m_capacity > 0) { + if (plugin->isCacheable(session, storedResult)) { LOGD("Entry cacheable"); if (m_keyValue.size() == m_capacity) { LOGD("Capacity reached."); evict(); } - m_keyUsage.push_front(keyToString(key)); - m_keyValue[keyToString(key)] = std::make_pair(result, m_keyUsage.begin()); + std::string cacheKey = keyToString(key); + m_keyUsage.push_front(cacheKey); + m_keyValue[cacheKey] = std::make_tuple(storedResult, session, m_keyUsage.begin()); } } - return plugin->toResult(result); + return plugin->toResult(session, storedResult); } } // namespace Cynara diff --git a/src/client-common/cache/CapacityCache.h b/src/client-common/cache/CapacityCache.h index 5bb083e..4218078 100644 --- a/src/client-common/cache/CapacityCache.h +++ b/src/client-common/cache/CapacityCache.h @@ -24,6 +24,7 @@ #define SRC_CLIENT_COMMON_CACHE_CAPACITYCACHE_H_ #include +#include #include #include @@ -46,15 +47,13 @@ public: private: typedef std::list KeyUsageList; typedef std::unordered_map> KeyValueMap; + std::tuple> KeyValueMap; static std::string keyToString(const PolicyKey &key); void evict(void); std::size_t m_capacity; - ClientSession m_session; KeyUsageList m_keyUsage; KeyValueMap m_keyValue; diff --git a/src/client-common/plugins/NaiveInterpreter.h b/src/client-common/plugins/NaiveInterpreter.h index 04d05de..e306ab7 100644 --- a/src/client-common/plugins/NaiveInterpreter.h +++ b/src/client-common/plugins/NaiveInterpreter.h @@ -29,13 +29,15 @@ namespace Cynara { class NaiveInterpreter : public InterpreterInterface { - bool isUsable(const PolicyResult &result UNUSED) { + bool isUsable(const ClientSession &session UNUSED, const ClientSession &prevSession UNUSED, + bool &updateSession UNUSED, PolicyResult &result UNUSED) { return true; } - bool isCacheable(const PolicyResult &result UNUSED) { + bool isCacheable(const ClientSession &session UNUSED, + const PolicyResult &result UNUSED) { return true; } - int toResult(const PolicyResult &result) { + int toResult(const ClientSession &session UNUSED, PolicyResult &result) { if (result.policyType() == PredefinedPolicyType::ALLOW) return CYNARA_API_ACCESS_ALLOWED; else diff --git a/src/client-common/plugins/PluginInterface.h b/src/client-common/plugins/PluginInterface.h index 5f3a947..54bd341 100644 --- a/src/client-common/plugins/PluginInterface.h +++ b/src/client-common/plugins/PluginInterface.h @@ -25,6 +25,7 @@ #include +#include #include namespace Cynara { @@ -34,13 +35,14 @@ typedef std::shared_ptr InterpreterInterfacePtr; class InterpreterInterface { public: - virtual bool isCacheable(const PolicyResult &result) = 0; - virtual bool isUsable(const PolicyResult &result) = 0; - virtual int toResult(const PolicyResult &result) = 0; + 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_ -- 2.7.4 From 9018caa487c2037baf70868a72b0b2cc39ce7217 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Tue, 16 Sep 2014 12:53:09 +0200 Subject: [PATCH 10/16] Fix cache update method Support update with existing entry. Change-Id: I0a242c9580ae0a521fddb8bf4fc4c2b8be3507c0 --- src/client-common/cache/CapacityCache.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index 04f1cb5..c6449bc 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -119,15 +119,31 @@ int CapacityCache::update(const ClientSession &session, PolicyResult storedResult = result; if (m_capacity > 0) { + std::string cacheKey = keyToString(key); + auto resultIt = m_keyValue.find(cacheKey); if (plugin->isCacheable(session, storedResult)) { LOGD("Entry cacheable"); if (m_keyValue.size() == m_capacity) { LOGD("Capacity reached."); evict(); } - std::string cacheKey = keyToString(key); - m_keyUsage.push_front(cacheKey); + + //Move value usage to front + if (resultIt != m_keyValue.end()) { + auto usageIt = std::get<2>(resultIt->second); + m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, usageIt); + } else { + m_keyUsage.push_front(cacheKey); + } + m_keyValue[cacheKey] = std::make_tuple(storedResult, session, m_keyUsage.begin()); + } else { + //Remove element + if (resultIt != m_keyValue.end()) { + auto usageIt = std::get<2>(resultIt->second); + m_keyUsage.erase(usageIt); + m_keyValue.erase(resultIt); + } } } return plugin->toResult(session, storedResult); -- 2.7.4 From 4c2b3b8d0ce17221e77bcda10be4ef992d82ba72 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 18 Sep 2014 17:33:53 +0200 Subject: [PATCH 11/16] Split PolicyResult declaration and definition PolicyResult header will be included in package for external plugin implementations. Change-Id: Ic5224af395b9fd86f57138566295961e80ee8f12 --- src/common/CMakeLists.txt | 1 + src/common/types/PolicyResult.cpp | 64 +++++++++++++++++++++++++++++++++++++++ src/common/types/PolicyResult.h | 53 +++++++++----------------------- test/CMakeLists.txt | 1 + 4 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 src/common/types/PolicyResult.cpp diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d52ddd5..461450a 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -49,6 +49,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/types/PolicyBucket.cpp ${COMMON_PATH}/types/PolicyKey.cpp ${COMMON_PATH}/types/PolicyKeyHelpers.cpp + ${COMMON_PATH}/types/PolicyResult.cpp ) IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") diff --git a/src/common/types/PolicyResult.cpp b/src/common/types/PolicyResult.cpp new file mode 100644 index 0000000..010139d --- /dev/null +++ b/src/common/types/PolicyResult.cpp @@ -0,0 +1,64 @@ +/* + * 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/PolicyResult.cpp + * @author Aleksander Zdyb + * @author Zofia Abramowska + * @version 1.0 + * @brief PolicyResult implementation + */ + +#include "PolicyResult.h" + +namespace Cynara { + +PolicyResult::PolicyResult() : m_type(PredefinedPolicyType::DENY) {} + +PolicyResult::PolicyResult(const PolicyType &policyType) : m_type(policyType) {} + +PolicyResult::PolicyResult(const PolicyType &policyType, const PolicyMetadata &metadata) + : m_type(policyType) , m_metadata(metadata) {} + +const PolicyType &PolicyResult::policyType(void) const { + return m_type; +} + +const PolicyResult::PolicyMetadata &PolicyResult::metadata(void) const { + return m_metadata; +} + +bool PolicyResult::operator <(const PolicyResult &other) const { + return this->m_type < other.m_type; +} + +bool PolicyResult::operator ==(const PolicyResult &other) const { + return std::tie(m_type, m_metadata) == std::tie(other.m_type, other.m_metadata); +} + +bool PolicyResult::operator !=(const PolicyResult &other) const { + return !(*this == other); +} + +bool PolicyResult::operator ==(const PolicyType &policyType) const { + return (m_type == policyType) && m_metadata.empty(); +} + +bool PolicyResult::operator !=(const PolicyType &policyType) const { + return !(*this == policyType); +} + +} // namespace Cynara + diff --git a/src/common/types/PolicyResult.h b/src/common/types/PolicyResult.h index 28974d7..ae81d15 100644 --- a/src/common/types/PolicyResult.h +++ b/src/common/types/PolicyResult.h @@ -16,12 +16,13 @@ /** * @file src/common/types/PolicyResult.h * @author Aleksander Zdyb + * @author Zofia Abramowska * @version 1.0 * @brief Definitions of PolicyResult and friends */ -#ifndef POLICYRESULT_H_ -#define POLICYRESULT_H_ +#ifndef SRC_COMMON_TYPES_POLICYRESULT_H_ +#define SRC_COMMON_TYPES_POLICYRESULT_H_ #include "types/PolicyType.h" @@ -33,47 +34,23 @@ class PolicyResult { public: typedef std::string PolicyMetadata; -public: - PolicyResult() : m_type(PredefinedPolicyType::DENY) {} - PolicyResult(const PolicyType &policyType) : m_type(policyType) {} - PolicyResult(const PolicyType &policyType, const PolicyMetadata &metadata) - : m_type(policyType), m_metadata(metadata) {} + PolicyResult(); + PolicyResult(const PolicyType &policyType); + PolicyResult(const PolicyType &policyType, const PolicyMetadata &metadata); + + const PolicyType &policyType(void) const; + const PolicyMetadata &metadata(void) const; + bool operator <(const PolicyResult &other) const; + bool operator ==(const PolicyResult &other) const; + bool operator !=(const PolicyResult &other) const; + bool operator ==(const PolicyType &policyType) const; + bool operator !=(const PolicyType &policyType) const; private: PolicyType m_type; PolicyMetadata m_metadata; - -public: - const PolicyType &policyType() const { - return m_type; - } - - const PolicyMetadata& metadata() const { - return m_metadata; - } - - bool operator <(const PolicyResult &other) const { - return this->m_type < other.m_type; - } - - bool operator ==(const PolicyResult &other) const { - return std::tie(m_type, m_metadata) == std::tie(other.m_type, other.m_metadata); - } - - bool operator !=(const PolicyResult &other) const { - return !(*this == other); - } - - bool operator ==(const PolicyType &policyType) const { - return (m_type == policyType) && m_metadata.empty(); - } - - bool operator !=(const PolicyType &policyType) const { - return !(*this == policyType); - } }; } // namespace Cynara - -#endif /* POLICYRESULT_H_ */ +#endif /* SRC_COMMON_TYPES_POLICYRESULT_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 47bcfab..62bdbaa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,6 +25,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/types/PolicyBucket.cpp ${CYNARA_SRC}/common/types/PolicyKey.cpp ${CYNARA_SRC}/common/types/PolicyKeyHelpers.cpp + ${CYNARA_SRC}/common/types/PolicyResult.cpp ${CYNARA_SRC}/common/types/PolicyType.cpp ${CYNARA_SRC}/storage/BucketDeserializer.cpp ${CYNARA_SRC}/storage/InMemoryStorageBackend.cpp -- 2.7.4 From abb2d89db389d6636c327343b7e6292a12155bd1 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 18 Sep 2014 18:37:40 +0200 Subject: [PATCH 12/16] Add cynara external plugins Add interface for creating external cynara plugin to enable custom policy types support. Change-Id: I43bd31a3e48f9667964107dd243f2286e7ffae8a --- packaging/cynara.spec | 14 ++++ pkgconfig/CMakeLists.txt | 1 + pkgconfig/cynara-plugin/CMakeLists.txt | 25 +++++++ pkgconfig/cynara-plugin/cynara-plugin.pc.in | 11 +++ src/common/CMakeLists.txt | 5 ++ src/include/CMakeLists.txt | 1 + src/include/cynara-plugin.h | 107 ++++++++++++++++++++++++++++ 7 files changed, 164 insertions(+) create mode 100644 pkgconfig/cynara-plugin/CMakeLists.txt create mode 100644 pkgconfig/cynara-plugin/cynara-plugin.pc.in create mode 100644 src/include/cynara-plugin.h diff --git a/packaging/cynara.spec b/packaging/cynara.spec index c25347f..6abd205 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -141,6 +141,14 @@ Requires: libcynara-commons = %{version}-%{release} cynara common library (devel) with common functionalities ####################################################### +%package -n libcynara-plugin-devel +Summary: Cynara - cynara plugin library (devel) +Requires: libcynara-commons-devel = %{version}-%{release} + +%description -n libcynara-plugin-devel +cynara plugin library (devel) with plugin definitions + +####################################################### %package -n libcynara-creds-commons Summary: Base library for cynara credentials helpers @@ -451,8 +459,14 @@ fi %{_libdir}/libcynara-commons.so.* %files -n libcynara-commons-devel +%{_includedir}/cynara/types/PolicyResult.h +%{_includedir}/cynara/types/PolicyType.h %{_libdir}/libcynara-commons.so +%files -n libcynara-plugin-devel +%{_includedir}/cynara/cynara-plugin.h +%{_libdir}/pkgconfig/cynara-plugin.pc + %files -n cynara-tests %manifest cynara-tests.manifest %attr(755,root,root) /usr/bin/cynara-tests diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index 9d4600f..a93ae55 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -23,4 +23,5 @@ ADD_SUBDIRECTORY(cynara-admin) ADD_SUBDIRECTORY(cynara-creds-commons) ADD_SUBDIRECTORY(cynara-creds-dbus) ADD_SUBDIRECTORY(cynara-creds-socket) +ADD_SUBDIRECTORY(cynara-plugin) ADD_SUBDIRECTORY(cynara-session) diff --git a/pkgconfig/cynara-plugin/CMakeLists.txt b/pkgconfig/cynara-plugin/CMakeLists.txt new file mode 100644 index 0000000..1ea74a5 --- /dev/null +++ b/pkgconfig/cynara-plugin/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 CMakeLists.txt +# @author Zofia Abramowska +# + +CONFIGURE_FILE(cynara-plugin.pc.in cynara-plugin.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-plugin/cynara-plugin.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig + ) diff --git a/pkgconfig/cynara-plugin/cynara-plugin.pc.in b/pkgconfig/cynara-plugin/cynara-plugin.pc.in new file mode 100644 index 0000000..c14de16 --- /dev/null +++ b/pkgconfig/cynara-plugin/cynara-plugin.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: cynara-plugin +Description: Cynara plugin definition package +Version: @CYNARA_VERSION@ +Requires: +Libs: -L${libdir} -lcynara-commons +Cflags: -I${includedir}/cynara diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 461450a..77c7d56 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -82,3 +82,8 @@ TARGET_LINK_LIBRARIES(${TARGET_CYNARA_COMMON} ) INSTALL(TARGETS ${TARGET_CYNARA_COMMON} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(FILES + ${COMMON_PATH}/types/PolicyResult.h + ${COMMON_PATH}/types/PolicyType.h + DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/types + ) diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index 1be6e10..cb9d00c 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-creds-commons.h ${CYNARA_PATH}/include/cynara-creds-dbus.h ${CYNARA_PATH}/include/cynara-creds-socket.h + ${CYNARA_PATH}/include/cynara-plugin.h ${CYNARA_PATH}/include/cynara-session.h DESTINATION ${INCLUDE_INSTALL_DIR}/cynara ) diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h new file mode 100644 index 0000000..83956fe --- /dev/null +++ b/src/include/cynara-plugin.h @@ -0,0 +1,107 @@ +/* + * 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-plugin.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines cynara side external plugin interface + */ + +#ifndef CYNARA_PLUGIN_H_ +#define CYNARA_PLUGIN_H_ + +#include +#include +#include + +#include +#include + +namespace Cynara { + +class ExternalPluginInterface; + +extern "C" { +typedef ExternalPluginInterface *(*createPlugin)(void); +} + +//These typedefs will be defined in external headers +typedef std::string PluginData; +typedef std::string AgentType; +typedef std::vector PolicyTypes; + +/** + * A class defining external plugins interface. + * These plugins work inside of cynara and either can produce + * response through check instantly or require communication + * with given type of agent. Agent must be registered through + * cynara-agent API. + */ + +class ExternalPluginInterface { +public: + /** + * Enum indicating status of calling plugin method. + */ + enum class PluginStatus { + SUCCESS, /** < update() finished successfully*/ + ANSWER_READY, /** < check() returns answer immediately through argument*/ + ANSWER_NOTREADY, /** < check() cannot return answer immediately, + < communication with agent is required */ + ERROR /** < either check() or update() fails */ + }; + + /** + * 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 + * @param[in] user + * @param[in] privilege + * @param[out] result Immediate response (if available) + * @param[out] requiredAgent When ANSWER_NOTREADY, required AgentType to communicate with + * @param[out] pluginData Additional data, that will be passed to agent + * @return PluginStatus In case of success - either ANSWER_READY or ANSWER_NOTREADY, + * in case of error - ERROR + */ + virtual PluginStatus check(const std::string &client, const std::string &user, + const std::string &privilege, PolicyResult &result, + AgentType &requiredAgent, PluginData &pluginData) noexcept = 0; + + /** + * Updates response returned by agent + * @param[in] client + * @param[in] user + * @param[in] privilege + * @param[in] agentData Additional data, passed from agent + * @param[out] result Response interpreted from agent + * @return PluginStatus In case of success - SUCCESS, in case of error - ERROR + */ + virtual PluginStatus update(const std::string &client, const std::string &user, + const std::string &privilege, const PluginData &agentData, + PolicyResult &result) noexcept = 0; + + virtual ~ExternalPluginInterface() {}; + +}; + +} // namespace Cynara + +#endif /* CYNARA_PLUGIN_H_ */ -- 2.7.4 From fa70d3d34bf759389e67f52401adb334cf21ec2e Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 19 Sep 2014 16:42:02 +0200 Subject: [PATCH 13/16] Add PluginManager Add cynara service manager for loading and managing dynamic loaded plugins supporting custom policy types. Change-Id: I94c3bfa4842a6a8d0a078ac910aba5e54db7b468 --- src/service/CMakeLists.txt | 3 + src/service/logic/Logic.cpp | 28 ++++++-- src/service/logic/Logic.h | 7 ++ src/service/main/Cynara.cpp | 17 +++++ src/service/main/Cynara.h | 2 + src/service/main/pointers.h | 3 + src/service/plugin/PluginManager.cpp | 123 +++++++++++++++++++++++++++++++++++ src/service/plugin/PluginManager.h | 55 ++++++++++++++++ 8 files changed, 232 insertions(+), 6 deletions(-) create mode 100644 src/service/plugin/PluginManager.cpp create mode 100644 src/service/plugin/PluginManager.h diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index f1c4c8a..f8d2eb8 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -22,6 +22,7 @@ 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 ) @@ -29,6 +30,7 @@ SET(CYNARA_SOURCES INCLUDE_DIRECTORIES( ${CYNARA_SERVICE_PATH} ${CYNARA_PATH} + ${CYNARA_PATH}/include ) ADD_EXECUTABLE(${TARGET_CYNARA} ${CYNARA_SOURCES}) @@ -37,6 +39,7 @@ TARGET_LINK_LIBRARIES(${TARGET_CYNARA} ${CYNARA_DEP_LIBRARIES} ${TARGET_CYNARA_COMMON} ${TARGET_LIB_CYNARA_STORAGE} + dl ) INSTALL(TARGETS ${TARGET_CYNARA} DESTINATION ${BIN_INSTALL_DIR}) diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index d05f512..60a0cce 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -97,13 +97,29 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, LOGD("check of policy key <%s> returned DENY", key.toString().c_str()); return true; } - //todo pass question to proper plugin that: - // 1) returns false when answer has to be waited for (UI) - // 2) returns true if Response is to be generated - // In case 1) context should be saved in plugin in order to return answer when ready. - //in case no proper plugin is found - throw PluginNotFoundException(result); + ExternalPluginPtr plugin = m_pluginManager->getPlugin(result.policyType()); + 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); + + switch (ret) { + case ExternalPluginInterface::PluginStatus::ANSWER_READY: + return true; + case ExternalPluginInterface::PluginStatus::ANSWER_NOTREADY: + //todo send request to agent + //context should be saved in plugin in order to return answer when ready + return false; + default: + //todo make additional class + throw std::runtime_error("Plugin error"); + } } void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index 28fdeea..3c434a5 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -27,6 +27,7 @@ #include #include
+#include #include #include @@ -37,6 +38,10 @@ public: Logic(); virtual ~Logic(); + void bindPluginManager(PluginManagerPtr pluginManager) { + m_pluginManager = pluginManager; + } + void bindStorage(StoragePtr storage) { m_storage = storage; } @@ -46,6 +51,7 @@ public: } void unbindAll(void) { + m_pluginManager.reset(); m_storage.reset(); m_socketManager.reset(); } @@ -59,6 +65,7 @@ public: virtual void execute(RequestContextPtr context, SignalRequestPtr request); private: + PluginManagerPtr m_pluginManager; StoragePtr m_storage; SocketManagerPtr m_socketManager; diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index 4a4deb4..1a0d45e 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -58,12 +59,27 @@ const std::string Cynara::storageDir(void) { return dir; } +const std::string Cynara::pluginDir(void) { + std::string dir("/usr/lib/cynara/"); + +#ifdef CYNARA_LIB_PATH + dir = CYNARA_LIB_PATH; +#else + LOGW("Cynara compiled without CYNARA_LIB_PATH flag. Using default plugin directory."); +#endif + dir += "plugin/"; + LOGI("Cynara plugin path <%s>", dir.c_str()); + return dir; +} + void Cynara::init(void) { m_logic = std::make_shared(); + m_pluginManager = std::make_shared(pluginDir()); m_socketManager = std::make_shared(); m_storageBackend = std::make_shared(storageDir()); m_storage = std::make_shared(*m_storageBackend); + m_logic->bindPluginManager(m_pluginManager); m_logic->bindStorage(m_storage); m_logic->bindSocketManager(m_socketManager); @@ -90,6 +106,7 @@ void Cynara::finalize(void) { } m_logic.reset(); + m_pluginManager.reset(); m_socketManager.reset(); m_storageBackend.reset(); m_storage.reset(); diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h index ecdde62..e89eda3 100644 --- a/src/service/main/Cynara.h +++ b/src/service/main/Cynara.h @@ -30,10 +30,12 @@ namespace Cynara { class Cynara { private: LogicPtr m_logic; + PluginManagerPtr m_pluginManager; SocketManagerPtr m_socketManager; StoragePtr m_storage; StorageBackendPtr m_storageBackend; + static const std::string pluginDir(void); static const std::string storageDir(void); public: diff --git a/src/service/main/pointers.h b/src/service/main/pointers.h index 652dba3..e31eeb8 100644 --- a/src/service/main/pointers.h +++ b/src/service/main/pointers.h @@ -30,6 +30,9 @@ namespace Cynara { class Logic; typedef std::shared_ptr LogicPtr; +class PluginManager; +typedef std::shared_ptr PluginManagerPtr; + class SocketManager; typedef std::shared_ptr SocketManagerPtr; diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp new file mode 100644 index 0000000..3d21b49 --- /dev/null +++ b/src/service/plugin/PluginManager.cpp @@ -0,0 +1,123 @@ +/* + * 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/plugin/PluginManager.cpp + * @author Zofia Abramowska + * @version 1.0 + * @brief Definition of PluginManager class + */ + +#define _BSD_SOURCE_ + +#include +#include +#include +#include +#include + +#include + +#include "PluginManager.h" + + +namespace { + int pluginFilter(const struct dirent *ent) { +#ifdef _DIRENT_HAVE_D_TYPE + if (ent->d_type != DT_REG) { + return 0; + } +#endif + if (ent->d_name[0] == '.') { + return 0; + } + return 1; + } +} + +namespace Cynara { + +PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) { + loadPlugins(); +} + +ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) { + return m_plugins[pType]; +} + +void PluginManager::loadPlugins(void) { + struct dirent **nameList = NULL; + int fileAmount = scandir(m_dir.c_str(), &nameList, pluginFilter, alphasort); + + if (fileAmount < 0) { + auto error = strerror(errno); + LOGE("Couldn't scan for plugins in <%s> : <%s>", m_dir.c_str(), error); + return; + } + + std::unique_ptr> direntPtr(nameList, + [fileAmount](dirent** dirs) { + for (int i = 0; i < fileAmount; i++) { + free(dirs[i]); + } + free(dirs); + }); + for (int i = 0; i < fileAmount; i++) { + openPlugin(m_dir + nameList[i]->d_name); + } +} + +void PluginManager::openPlugin(const std::string &path) { + void *handle = dlopen(path.c_str(), RTLD_LAZY); + + if (!handle) { + LOGW("File could not be dlopened <%s> : <%s>", path.c_str(), dlerror()); + return; + } + PluginLibPtr handlePtr(handle, std::ptr_fun(dlclose)); + + //Flush any previous errors + dlerror(); + createPlugin func = reinterpret_cast(dlsym(handle, "create")); + + char *error; + if ((error = dlerror()) != NULL) { + LOGE("Couldn't resolve symbol from lib <%s> : <%s>", path.c_str(), error); + return; + } + + ExternalPluginPtr pluginPtr(func()); + + if (!pluginPtr) { + LOGE("Couldn't create plugin for <%s>", path.c_str()); + return; + } + + PolicyTypes policies = pluginPtr->getSupportedPolicyTypes(); + if (policies.empty()) { + LOGE("Plugin <%s> does not support any type!", path.c_str()); + return; + } + for (auto type : policies) { + if (!m_plugins.insert(std::make_pair(type, pluginPtr)).second) { + LOGW("policyType [%" PRIu16 "] was already supported.", type); + } + } + + m_pluginLibs.push_back(std::move(handlePtr)); +} + +} // namespace Cynara + diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h new file mode 100644 index 0000000..6338cad --- /dev/null +++ b/src/service/plugin/PluginManager.h @@ -0,0 +1,55 @@ +/* + * 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/plugin/PluginManager.h + * @author Zofia Abramowska + * @version 1.0 + * @brief Declaration of PluginManager class + */ + +#ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ +#define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ + +#include +#include +#include +#include + +#include + +namespace Cynara { +typedef std::shared_ptr ExternalPluginPtr; + +class PluginManager { +public: + PluginManager(const std::string &pluginDir); + ExternalPluginPtr getPlugin(PolicyType pType); + ~PluginManager() {} + +private: + typedef std::unique_ptr> PluginLibPtr; + typedef std::list PluginLibs; + + std::string m_dir; + std::map m_plugins; + PluginLibs m_pluginLibs; + + void loadPlugins(void); + void openPlugin(const std::string &path); +}; + +} // namespace Cynara +#endif /* SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ */ -- 2.7.4 From 401f59efe466d7bc55174666a598d49941bc3ff8 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Tue, 7 Oct 2014 14:46:47 +0200 Subject: [PATCH 14/16] Add PluginErrorException Add exception class for plugin processing error. Change-Id: I26090bd3a54bdbc4767fd05735b5b06fae523b2f --- src/common/exceptions/PluginErrorException.h | 48 ++++++++++++++++++++++++++++ src/service/logic/Logic.cpp | 7 ++-- 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/common/exceptions/PluginErrorException.h diff --git a/src/common/exceptions/PluginErrorException.h b/src/common/exceptions/PluginErrorException.h new file mode 100644 index 0000000..a29eab5 --- /dev/null +++ b/src/common/exceptions/PluginErrorException.h @@ -0,0 +1,48 @@ +/* + * 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/exceptions/PluginErrorException.h + * @author Zofia Abramowska + * @version 1.0 + * @brief Implementation of PluginErrorException + */ +#ifndef SRC_COMMON_EXCEPTIONS_PLUGINERROREXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_PLUGINERROREXCEPTION_H_ + +#include +#include + +namespace Cynara { + +class PluginErrorException : public Exception { +public: + PluginErrorException(const PolicyKey &key) { + m_message = "Plugin couldn't get result for user <" + key.user().toString() + ">, " + "client <" + key.client().toString() + ">, " + "privilege <" + key.privilege().toString() + ">"; + } + + const std::string message(void) const { + return m_message; + } + +private: + std::string m_message; +}; + +} // namespace Cynara + +#endif // SRC_COMMON_EXCEPTIONS_PLUGINERROREXCEPTION_H_ diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 60a0cce..1787575 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -22,10 +22,12 @@ #include #include -#include #include #include #include +#include +#include + #include #include
@@ -117,8 +119,7 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, //context should be saved in plugin in order to return answer when ready return false; default: - //todo make additional class - throw std::runtime_error("Plugin error"); + throw PluginErrorException(key); } } -- 2.7.4 From adedddc8dbb050342f883b8966b9fe3fad5207f8 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 14 Oct 2014 08:47:31 +0200 Subject: [PATCH 15/16] Remove "noexcept" keyword from admin's Logic class We don't want cause application termination. All exceptions should be caught and handled. Change-Id: Ic245fb42a8b8fa7a7d83665ce95c4acb89c5b964 --- src/admin/api/ApiInterface.h | 10 +++++----- src/admin/logic/Logic.cpp | 8 ++++---- src/admin/logic/Logic.h | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index bbfe98d..62c40e5 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -42,13 +42,13 @@ public: virtual ~ApiInterface() {}; virtual int setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove) noexcept = 0; - virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) - noexcept = 0; - virtual int removeBucket(const PolicyBucketId &bucket) noexcept = 0; + const std::map> &remove) = 0; + virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult) = 0; + virtual int removeBucket(const PolicyBucketId &bucket) = 0; virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, - const PolicyKey &key, PolicyResult &result) noexcept = 0; + const PolicyKey &key, PolicyResult &result) = 0; }; diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 6906056..3b004d9 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -112,21 +112,21 @@ int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { } int Logic::setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove) noexcept { + const std::map> &remove) { return askCynaraAndInterpreteCodeResponse(insertOrUpdate, remove); } int Logic::insertOrUpdateBucket(const PolicyBucketId &bucket, - const PolicyResult &policyResult) noexcept { + const PolicyResult &policyResult) { return askCynaraAndInterpreteCodeResponse(bucket, policyResult); } -int Logic::removeBucket(const PolicyBucketId &bucket) noexcept { +int Logic::removeBucket(const PolicyBucketId &bucket) { return askCynaraAndInterpreteCodeResponse(bucket); } int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, - PolicyResult &result) noexcept { + PolicyResult &result) { try { if (!ensureConnection()) { LOGE("Cannot connect to cynara. Service not available."); diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index 527e992..a8688c2 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -44,13 +44,13 @@ public: virtual ~Logic() {}; virtual int setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove) noexcept; - virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) - noexcept; - virtual int removeBucket(const PolicyBucketId &bucket) noexcept; + const std::map> &remove); + virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult); + virtual int removeBucket(const PolicyBucketId &bucket); virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, - const PolicyKey &key, PolicyResult &result) noexcept; + const PolicyKey &key, PolicyResult &result); }; } // namespace Cynara -- 2.7.4 From 8c151752c38ea5572e4d2efbdc3ae55292ae8820 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 14 Oct 2014 09:21:41 +0200 Subject: [PATCH 16/16] Clean up exception classes Some minor clean-ups in exceptions classes: * remove "noexcept" keyword from exception classes; * catch exceptions in Exception::what(); * correcting comments; * adding missing virtual keyword; * rearranging public and private sections. Change-Id: I99c382838adb22429a7ea8ac35974c988b3d3f33 --- .../exceptions/BucketDeserializationException.h | 2 +- src/common/exceptions/BucketNotExistsException.h | 11 ++++----- .../exceptions/BucketRecordCorruptedException.h | 27 +++++++++++----------- .../exceptions/BucketSerializationException.h | 2 +- src/common/exceptions/CannotCreateFileException.h | 2 +- src/common/exceptions/DatabaseException.h | 3 ++- .../exceptions/DefaultBucketDeletionException.h | 2 +- .../exceptions/DefaultBucketSetNoneException.h | 2 +- .../exceptions/DescriptorNotExistsException.h | 8 +++---- src/common/exceptions/Exception.h | 8 +++++-- src/common/exceptions/FileNotFoundException.h | 2 +- src/common/exceptions/InitException.h | 2 +- src/common/exceptions/InvalidProtocolException.h | 14 +++++------ src/common/exceptions/NoMemoryException.h | 2 +- src/common/exceptions/NotImplementedException.h | 2 +- src/common/exceptions/NullPointerException.h | 10 ++++---- src/common/exceptions/OutOfDataException.h | 8 +++---- src/common/exceptions/PluginNotFoundException.h | 8 +++---- src/common/exceptions/UnexpectedErrorException.h | 8 +++---- 19 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/common/exceptions/BucketDeserializationException.h b/src/common/exceptions/BucketDeserializationException.h index c6b6f1d..c5670c8 100644 --- a/src/common/exceptions/BucketDeserializationException.h +++ b/src/common/exceptions/BucketDeserializationException.h @@ -30,7 +30,7 @@ namespace Cynara { class BucketDeserializationException : public DatabaseException { public: BucketDeserializationException(const PolicyBucketId &bucketId) : m_bucketId(bucketId) {} - ~BucketDeserializationException() noexcept {}; + virtual ~BucketDeserializationException() {}; const std::string message(void) const { if (m_message.empty()) { diff --git a/src/common/exceptions/BucketNotExistsException.h b/src/common/exceptions/BucketNotExistsException.h index 7802210..9ba9505 100644 --- a/src/common/exceptions/BucketNotExistsException.h +++ b/src/common/exceptions/BucketNotExistsException.h @@ -34,19 +34,18 @@ class BucketNotExistsException : public Exception { public: BucketNotExistsException() = delete; BucketNotExistsException(const PolicyBucketId &bucketId) : m_bucketId(bucketId) {} - virtual ~BucketNotExistsException() noexcept {}; + virtual ~BucketNotExistsException() {}; virtual const std::string message(void) const { return "BucketNotExistsException"; } -private: - PolicyBucketId m_bucketId; - -public: - const PolicyBucketId &bucketId() const { + const PolicyBucketId &bucketId(void) const { return m_bucketId; } + +private: + PolicyBucketId m_bucketId; }; } /* namespace Cynara */ diff --git a/src/common/exceptions/BucketRecordCorruptedException.h b/src/common/exceptions/BucketRecordCorruptedException.h index 4511fb5..92b29f7 100644 --- a/src/common/exceptions/BucketRecordCorruptedException.h +++ b/src/common/exceptions/BucketRecordCorruptedException.h @@ -31,7 +31,7 @@ namespace Cynara { class BucketRecordCorruptedException : public DatabaseException { public: BucketRecordCorruptedException(void) = delete; - virtual ~BucketRecordCorruptedException() noexcept {}; + virtual ~BucketRecordCorruptedException() {}; BucketRecordCorruptedException(const std::string &line) : m_lineNumber(0), m_line(line) {} @@ -60,6 +60,18 @@ public: return m_whatMsg; } + const std::string &filename(void) const { + return m_filename; + } + + const std::string &line(void) const { + return m_line; + } + + size_t lineNumber(void) const { + return m_lineNumber; + } + protected: inline std::string slicedLine(void) const { return m_line.substr(0, 50) + (m_line.size() > 50 ? "..." : ""); @@ -80,19 +92,6 @@ private: std::string m_line; std::string m_filename; mutable std::string m_whatMsg; - -public: - const std::string &filename(void) const { - return m_filename; - } - - const std::string &line(void) const { - return m_line; - } - - size_t lineNumber(void) const { - return m_lineNumber; - } }; } /* namespace Cynara */ diff --git a/src/common/exceptions/BucketSerializationException.h b/src/common/exceptions/BucketSerializationException.h index f6dba4c..1e02823 100644 --- a/src/common/exceptions/BucketSerializationException.h +++ b/src/common/exceptions/BucketSerializationException.h @@ -30,7 +30,7 @@ namespace Cynara { class BucketSerializationException : public DatabaseException { public: BucketSerializationException(const PolicyBucketId &bucketId) : m_bucketId(bucketId) {} - ~BucketSerializationException() noexcept {}; + virtual ~BucketSerializationException() {}; const std::string message(void) const { if (m_message.empty()) { diff --git a/src/common/exceptions/CannotCreateFileException.h b/src/common/exceptions/CannotCreateFileException.h index 4195156..67c1d67 100644 --- a/src/common/exceptions/CannotCreateFileException.h +++ b/src/common/exceptions/CannotCreateFileException.h @@ -32,7 +32,7 @@ namespace Cynara { class CannotCreateFileException : public DatabaseException { public: CannotCreateFileException(const std::string &filename) : m_filename(filename) {}; - virtual ~CannotCreateFileException() noexcept {}; + virtual ~CannotCreateFileException() {}; const std::string message(void) const { if (m_message.empty()) { diff --git a/src/common/exceptions/DatabaseException.h b/src/common/exceptions/DatabaseException.h index 9cbd2b4..834d524 100644 --- a/src/common/exceptions/DatabaseException.h +++ b/src/common/exceptions/DatabaseException.h @@ -27,7 +27,8 @@ namespace Cynara { class DatabaseException : public Exception { - +public: + virtual ~DatabaseException() {}; }; } /* namespace Cynara */ diff --git a/src/common/exceptions/DefaultBucketDeletionException.h b/src/common/exceptions/DefaultBucketDeletionException.h index 9b75a00..a4742be 100644 --- a/src/common/exceptions/DefaultBucketDeletionException.h +++ b/src/common/exceptions/DefaultBucketDeletionException.h @@ -32,7 +32,7 @@ namespace Cynara { class DefaultBucketDeletionException : public Exception { public: DefaultBucketDeletionException() = default; - virtual ~DefaultBucketDeletionException() noexcept {}; + virtual ~DefaultBucketDeletionException() {}; virtual const std::string message(void) const { return "DefaultBucketDeletionException"; diff --git a/src/common/exceptions/DefaultBucketSetNoneException.h b/src/common/exceptions/DefaultBucketSetNoneException.h index b7975cd..243c4d8 100644 --- a/src/common/exceptions/DefaultBucketSetNoneException.h +++ b/src/common/exceptions/DefaultBucketSetNoneException.h @@ -32,7 +32,7 @@ namespace Cynara { class DefaultBucketSetNoneException : public Exception { public: DefaultBucketSetNoneException() = default; - virtual ~DefaultBucketSetNoneException() noexcept {}; + virtual ~DefaultBucketSetNoneException() {}; virtual const std::string message(void) const { return "DefaultBucketSetNoneException"; diff --git a/src/common/exceptions/DescriptorNotExistsException.h b/src/common/exceptions/DescriptorNotExistsException.h index badb64a..3535b91 100644 --- a/src/common/exceptions/DescriptorNotExistsException.h +++ b/src/common/exceptions/DescriptorNotExistsException.h @@ -32,9 +32,6 @@ namespace Cynara { class DescriptorNotExistsException : public Exception { -private: - std::string m_whatMsg; - public: DescriptorNotExistsException() = delete; DescriptorNotExistsException(int desc) { @@ -43,11 +40,14 @@ public: m_whatMsg = stream.str(); } - virtual ~DescriptorNotExistsException() noexcept {}; + virtual ~DescriptorNotExistsException() {}; virtual const std::string message(void) const { return m_whatMsg; } + +private: + std::string m_whatMsg; }; } // namespace Cynara diff --git a/src/common/exceptions/Exception.h b/src/common/exceptions/Exception.h index 4f5f5eb..c5eb709 100644 --- a/src/common/exceptions/Exception.h +++ b/src/common/exceptions/Exception.h @@ -33,11 +33,15 @@ public: m_backtrace = Backtrace::getBacktrace(); } - virtual ~Exception() noexcept {}; + virtual ~Exception() {}; virtual const char *what(void) const noexcept { if(m_whatMessage.empty()) { - m_whatMessage = message() + " From: " + m_backtrace; + try { + m_whatMessage = message() + " From: " + m_backtrace; + } + catch (...) { + } } return m_whatMessage.c_str(); } diff --git a/src/common/exceptions/FileNotFoundException.h b/src/common/exceptions/FileNotFoundException.h index e7aeead..4c446e2 100644 --- a/src/common/exceptions/FileNotFoundException.h +++ b/src/common/exceptions/FileNotFoundException.h @@ -32,7 +32,7 @@ namespace Cynara { class FileNotFoundException : public DatabaseException { public: FileNotFoundException(const std::string &filename) : m_filename(filename) {}; - virtual ~FileNotFoundException() noexcept {}; + virtual ~FileNotFoundException() {}; const std::string message(void) const { if (m_message.empty()) { diff --git a/src/common/exceptions/InitException.h b/src/common/exceptions/InitException.h index c93155c..cdb09a2 100644 --- a/src/common/exceptions/InitException.h +++ b/src/common/exceptions/InitException.h @@ -32,7 +32,7 @@ namespace Cynara { class InitException : public Exception { public: InitException() = default; - virtual ~InitException() noexcept {}; + virtual ~InitException() {}; virtual const std::string message(void) const { return "InitException"; diff --git a/src/common/exceptions/InvalidProtocolException.h b/src/common/exceptions/InvalidProtocolException.h index 89d0e4b..9b6a740 100644 --- a/src/common/exceptions/InvalidProtocolException.h +++ b/src/common/exceptions/InvalidProtocolException.h @@ -38,11 +38,6 @@ public: Other }; -private: - std::string m_whatMessage; - ExceptionType m_exceptionType; - -public: InvalidProtocolException(ExceptionType exceptionType) : m_exceptionType(exceptionType) { switch(m_exceptionType) { @@ -56,18 +51,21 @@ public: m_whatMessage = "Unknown problem"; break; } - } - virtual ~InvalidProtocolException() noexcept {}; + virtual ~InvalidProtocolException() {}; virtual const std::string message(void) const { return m_whatMessage; } - ExceptionType exceptionTyp(void) const { + ExceptionType exceptionType(void) const { return m_exceptionType; } + +private: + std::string m_whatMessage; + ExceptionType m_exceptionType; }; } // namespace Cynara diff --git a/src/common/exceptions/NoMemoryException.h b/src/common/exceptions/NoMemoryException.h index d8a6086..2eca090 100644 --- a/src/common/exceptions/NoMemoryException.h +++ b/src/common/exceptions/NoMemoryException.h @@ -37,7 +37,7 @@ public: m_whatMessage = "NoMemoryException with message <" + errorMsg + ">"; } - virtual ~NoMemoryException() noexcept {}; + virtual ~NoMemoryException() {}; virtual const std::string message(void) const { return m_whatMessage; diff --git a/src/common/exceptions/NotImplementedException.h b/src/common/exceptions/NotImplementedException.h index 1496fd7..8ca3762 100644 --- a/src/common/exceptions/NotImplementedException.h +++ b/src/common/exceptions/NotImplementedException.h @@ -32,7 +32,7 @@ namespace Cynara { class NotImplementedException : public Exception { public: NotImplementedException() = default; - virtual ~NotImplementedException() noexcept {}; + virtual ~NotImplementedException() {}; virtual const std::string message(void) const { return "NotImplementedException"; diff --git a/src/common/exceptions/NullPointerException.h b/src/common/exceptions/NullPointerException.h index 47e4239..e735555 100644 --- a/src/common/exceptions/NullPointerException.h +++ b/src/common/exceptions/NullPointerException.h @@ -17,7 +17,7 @@ * @file src/common/exceptions/NullPointerException.h * @author Lukasz Wojciechowski * @version 1.0 - * @brief Implementation of OutOfDataException + * @brief Implementation of NullPointerException */ #ifndef SRC_COMMON_EXCEPTIONS_NULLPOINTEREXCEPTION_H_ @@ -31,9 +31,6 @@ namespace Cynara { class NullPointerException : public Exception { -private: - std::string m_whatMsg; - public: NullPointerException() = delete; NullPointerException(const char *varName) { @@ -42,11 +39,14 @@ public: + std::string(">"); } - virtual ~NullPointerException() noexcept {}; + virtual ~NullPointerException() {}; virtual const std::string message(void) const { return m_whatMsg; } + +private: + std::string m_whatMsg; }; } // namespace Cynara diff --git a/src/common/exceptions/OutOfDataException.h b/src/common/exceptions/OutOfDataException.h index 716df13..6420819 100644 --- a/src/common/exceptions/OutOfDataException.h +++ b/src/common/exceptions/OutOfDataException.h @@ -32,9 +32,6 @@ namespace Cynara { class OutOfDataException : public Exception { -private: - std::string m_whatMsg; - public: OutOfDataException() = delete; OutOfDataException(size_t dataRange, size_t accessTry) { @@ -44,11 +41,14 @@ public: m_whatMsg = stream.str(); } - virtual ~OutOfDataException() noexcept {}; + virtual ~OutOfDataException() {}; virtual const std::string message(void) const { return m_whatMsg; } + +private: + std::string m_whatMsg; }; } // namespace Cynara diff --git a/src/common/exceptions/PluginNotFoundException.h b/src/common/exceptions/PluginNotFoundException.h index 3604075..4492a53 100644 --- a/src/common/exceptions/PluginNotFoundException.h +++ b/src/common/exceptions/PluginNotFoundException.h @@ -32,9 +32,6 @@ namespace Cynara { class PluginNotFoundException : public Exception { -private: - std::string m_whatMessage; - public: PluginNotFoundException() = delete; PluginNotFoundException(const PolicyResult &result) { @@ -45,11 +42,14 @@ public: m_whatMessage = stream.str(); } - virtual ~PluginNotFoundException() noexcept {}; + virtual ~PluginNotFoundException() {}; virtual const std::string message(void) const { return m_whatMessage; } + +private: + std::string m_whatMessage; }; } // namespace Cynara diff --git a/src/common/exceptions/UnexpectedErrorException.h b/src/common/exceptions/UnexpectedErrorException.h index ed0b72c..3080c0f 100644 --- a/src/common/exceptions/UnexpectedErrorException.h +++ b/src/common/exceptions/UnexpectedErrorException.h @@ -31,9 +31,6 @@ namespace Cynara { class UnexpectedErrorException : public Exception { -private: - std::string m_whatMessage; - public: UnexpectedErrorException() = delete; UnexpectedErrorException(int errorCode, const char *errorMsg) { @@ -49,11 +46,14 @@ public: m_whatMessage = stream.str(); } - virtual ~UnexpectedErrorException() noexcept {}; + virtual ~UnexpectedErrorException() {}; virtual const std::string message(void) const { return m_whatMessage; } + +private: + std::string m_whatMessage; }; } // namespace Cynara -- 2.7.4