From 0ded5caa100a6802eb2f3e45e7b2073f0cef95eb Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Wed, 27 Aug 2014 09:18:02 +0200 Subject: [PATCH 01/16] Implement mechanism assuring integrity of database There is also added mechanism for cleaning up Cynara's database directory upon loading policies to memory. There is added test checking whether mechanism behaves as intended. Change-Id: I926d1aebf394c092e00731b73717e0e1c55bad0c --- packaging/cynara.spec | 3 +- src/storage/CMakeLists.txt | 1 + src/storage/InMemoryStorageBackend.cpp | 46 +++- src/storage/InMemoryStorageBackend.h | 10 +- src/storage/Integrity.cpp | 232 +++++++++++++++++++++ src/storage/Integrity.h | 71 +++++++ test/CMakeLists.txt | 1 + test/db/db6/_ | 0 test/db/db6/_additional | 1 + test/db/db6/_additional~ | 0 test/db/db6/_~ | 0 test/db/db6/buckets | 2 + test/db/db6/buckets~ | 2 + test/db/db6/guard | 0 .../fakeinmemorystoragebackend.h | 2 +- .../inmemeorystoragebackendfixture.h | 2 + .../inmemorystoragebackend.cpp | 38 +++- 17 files changed, 396 insertions(+), 15 deletions(-) create mode 100644 src/storage/Integrity.cpp create mode 100644 src/storage/Integrity.h create mode 100644 test/db/db6/_ create mode 100644 test/db/db6/_additional create mode 100644 test/db/db6/_additional~ create mode 100644 test/db/db6/_~ create mode 100644 test/db/db6/buckets create mode 100644 test/db/db6/buckets~ create mode 100644 test/db/db6/guard diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 213c94e..68d52ce 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -283,7 +283,7 @@ cp ./conf/creds.conf %{buildroot}/%{conf_path}/creds.conf mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants mkdir -p %{buildroot}/%{state_path} -mkdir -p %{buildroot}/%{tests_dir} +mkdir -p %{buildroot}/%{tests_dir}/empty_db cp -a db* %{buildroot}/%{tests_dir} ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket @@ -494,6 +494,7 @@ fi %manifest cynara-tests.manifest %attr(755,root,root) /usr/bin/cynara-tests %attr(755,root,root) %{tests_dir}/db*/* +%dir %attr(755,root,root) %{tests_dir}/empty_db %files -n libcynara-creds-commons %manifest libcynara-creds-commons.manifest diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt index 620dc2d..7bccc8c 100644 --- a/src/storage/CMakeLists.txt +++ b/src/storage/CMakeLists.txt @@ -25,6 +25,7 @@ SET(CYNARA_LIB_CYNARA_STORAGE_PATH ${CYNARA_PATH}/storage) SET(LIB_CYNARA_STORAGE_SOURCES ${CYNARA_LIB_CYNARA_STORAGE_PATH}/BucketDeserializer.cpp ${CYNARA_LIB_CYNARA_STORAGE_PATH}/InMemoryStorageBackend.cpp + ${CYNARA_LIB_CYNARA_STORAGE_PATH}/Integrity.cpp ${CYNARA_LIB_CYNARA_STORAGE_PATH}/Storage.cpp ${CYNARA_LIB_CYNARA_STORAGE_PATH}/StorageDeserializer.cpp ${CYNARA_LIB_CYNARA_STORAGE_PATH}/StorageSerializer.cpp diff --git a/src/storage/InMemoryStorageBackend.cpp b/src/storage/InMemoryStorageBackend.cpp index af18926..a2366e8 100644 --- a/src/storage/InMemoryStorageBackend.cpp +++ b/src/storage/InMemoryStorageBackend.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -43,6 +42,7 @@ #include #include +#include #include #include @@ -50,17 +50,28 @@ namespace Cynara { -const std::string InMemoryStorageBackend::m_indexFileName = "buckets"; +const std::string InMemoryStorageBackend::m_indexFilename = "buckets"; +const std::string InMemoryStorageBackend::m_backupFilenameSuffix = "~"; +const std::string InMemoryStorageBackend::m_bucketFilenamePrefix = "_"; void InMemoryStorageBackend::load(void) { - std::string indexFilename = m_dbPath + m_indexFileName; + Integrity integrity(m_dbPath, m_indexFilename, m_backupFilenameSuffix, m_bucketFilenamePrefix); + bool isBackupValid = integrity.backupGuardExists(); + std::string bucketSuffix = ""; + std::string indexFilename = m_dbPath + m_indexFilename; + + if (isBackupValid) { + bucketSuffix += m_backupFilenameSuffix; + indexFilename += m_backupFilenameSuffix; + } try { auto indexStream = std::make_shared(); openFileStream(indexStream, indexFilename); StorageDeserializer storageDeserializer(indexStream, - std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1)); + std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, + std::placeholders::_1, bucketSuffix)); storageDeserializer.initBuckets(buckets()); storageDeserializer.loadBuckets(buckets()); @@ -74,6 +85,13 @@ void InMemoryStorageBackend::load(void) { LOGN("Creating defaultBucket."); this->buckets().insert({ defaultPolicyBucketId, PolicyBucket(defaultPolicyBucketId) }); } + + if (isBackupValid) { + integrity.revalidatePrimaryDatabase(buckets()); + } + //in case there were unnecessary files in db directory + integrity.deleteNonIndexedFiles(std::bind(&InMemoryStorageBackend::hasBucket, this, + std::placeholders::_1)); } void InMemoryStorageBackend::save(void) { @@ -90,11 +108,19 @@ void InMemoryStorageBackend::save(void) { } auto indexStream = std::make_shared(); - openDumpFileStream(indexStream, m_dbPath + m_indexFileName); + std::string indexFilename = m_dbPath + m_indexFilename; + openDumpFileStream(indexStream, indexFilename + m_backupFilenameSuffix); StorageSerializer storageSerializer(indexStream); storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener, this, std::placeholders::_1)); + + Integrity integrity(m_dbPath, m_indexFilename, m_backupFilenameSuffix, m_bucketFilenamePrefix); + + integrity.syncDatabase(buckets(), true); + integrity.createBackupGuard(); + integrity.revalidatePrimaryDatabase(buckets()); + //guard is removed during revalidation } PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) { @@ -181,8 +207,9 @@ void InMemoryStorageBackend::openFileStream(std::shared_ptr strea // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); stream->open(filename); - if (!stream->is_open()) + if (!stream->is_open()) { throw FileNotFoundException(filename); + } } void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr stream, @@ -195,8 +222,8 @@ void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr s } std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( - const PolicyBucketId &bucketId) { - std::string bucketFilename = m_dbPath + "_" + bucketId; + const PolicyBucketId &bucketId, const std::string &filenameSuffix) { + std::string bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId + filenameSuffix; auto bucketStream = std::make_shared(); try { openFileStream(bucketStream, bucketFilename); @@ -208,7 +235,8 @@ std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( std::shared_ptr InMemoryStorageBackend::bucketDumpStreamOpener( const PolicyBucketId &bucketId) { - std::string bucketFilename = m_dbPath + "_" + bucketId; + std::string bucketFilename = m_dbPath + m_bucketFilenamePrefix + + bucketId + m_backupFilenameSuffix; auto bucketStream = std::make_shared(); openDumpFileStream(bucketStream, bucketFilename); diff --git a/src/storage/InMemoryStorageBackend.h b/src/storage/InMemoryStorageBackend.h index cc35f95..d03dd6c 100644 --- a/src/storage/InMemoryStorageBackend.h +++ b/src/storage/InMemoryStorageBackend.h @@ -62,15 +62,19 @@ public: protected: InMemoryStorageBackend() {} void openFileStream(std::shared_ptr stream, const std::string &filename); - std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId); + std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId, + const std::string &fileNameSuffix); - void openDumpFileStream(std::shared_ptr stream, const std::string &filename); + virtual void openDumpFileStream(std::shared_ptr stream, + const std::string &filename); std::shared_ptr bucketDumpStreamOpener(const PolicyBucketId &bucketId); private: std::string m_dbPath; Buckets m_buckets; - static const std::string m_indexFileName; + static const std::string m_indexFilename; + static const std::string m_backupFilenameSuffix; + static const std::string m_bucketFilenamePrefix; protected: virtual Buckets &buckets(void) { diff --git a/src/storage/Integrity.cpp b/src/storage/Integrity.cpp new file mode 100644 index 0000000..8057e9c --- /dev/null +++ b/src/storage/Integrity.cpp @@ -0,0 +1,232 @@ +/* + * 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/storage/Integrity.cpp + * @author Pawel Wieczorek + * @version 0.1 + * @brief Implementation of Cynara::Integrity + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Integrity.h" + +namespace Cynara { + +const std::string Integrity::m_guardFilename = "guard"; + +bool Integrity::backupGuardExists(void) const { + struct stat buffer; + std::string guardFilename = m_dbPath + m_guardFilename; + + int ret = stat(guardFilename.c_str(), &buffer); + + if (ret == 0) { + return true; + } else { + int err = errno; + if (err != ENOENT) { + LOGE("'stat' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + return false; + } +} + +void Integrity::createBackupGuard(void) const { + syncElement(m_dbPath + m_guardFilename, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC); + syncDirectory(m_dbPath); +} + +void Integrity::syncDatabase(const Buckets &buckets, bool syncBackup) { + std::string suffix = ""; + + if (syncBackup) { + suffix += m_backupFilenameSuffix; + } + + for (const auto &bucketIter : buckets) { + const auto &bucketId = bucketIter.first; + const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId + suffix; + + syncElement(bucketFilename); + } + + syncElement(m_dbPath + m_indexFilename + suffix); + syncDirectory(m_dbPath); +} + +void Integrity::revalidatePrimaryDatabase(const Buckets &buckets) { + createPrimaryHardLinks(buckets); + syncDatabase(buckets, false); + + deleteHardLink(m_dbPath + m_guardFilename); + syncDirectory(m_dbPath); + + deleteBackupHardLinks(buckets); +} + +void Integrity::deleteNonIndexedFiles(BucketPresenceTester tester) { + DIR *dirPtr = nullptr; + struct dirent *direntPtr; + + if ((dirPtr = opendir(m_dbPath.c_str())) == nullptr) { + int err = errno; + LOGE("'opendir' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + return; + } + + while (errno = 0, (direntPtr = readdir(dirPtr)) != nullptr) { + std::string filename = direntPtr->d_name; + //ignore all special files (working dir, parent dir, index) + if ("." == filename || ".." == filename || "buckets" == filename) { + continue; + } + + std::string bucketId; + auto nameLength = filename.length(); + auto prefixLength = m_bucketFilenamePrefix.length(); + + //remove if it is impossible that it is a bucket file + if (nameLength < prefixLength) { + deleteHardLink(m_dbPath + filename); + continue; + } + + //remove if there is no bucket filename prefix + //0 is returned from string::compare() if strings are equal + if (0 != filename.compare(0, prefixLength, m_bucketFilenamePrefix)) { + deleteHardLink(m_dbPath + filename); + continue; + } + + //remove if bucket is not in index + bucketId = filename.substr(prefixLength); + if (!tester(bucketId)) { + deleteHardLink(m_dbPath + filename); + } + } + + if (errno) { + int err = errno; + LOGE("'readdir' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + return; + } +} + +void Integrity::syncElement(const std::string &filename, int flags, mode_t mode) { + int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode)); + + if (fileFd < 0) { + int err = errno; + if (err != EEXIST) { + LOGE("'open' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } else { + throw CannotCreateFileException(filename); + } + } + + int ret = fsync(fileFd); + + if (ret < 0) { + int err = errno; + LOGE("'fsync' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + + ret = close(fileFd); + + if (ret < 0) { + int err = errno; + LOGE("'close' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } +} + +// from: man 2 fsync +// Calling fsync() does not necessarily ensure that the entry in the directory containing +// the file has also reached disk. For that an explicit fsync() on a file descriptor for +// the directory is also needed. +void Integrity::syncDirectory(const std::string &dirname, mode_t mode) { + syncElement(dirname, O_DIRECTORY, mode); +} + +void Integrity::createPrimaryHardLinks(const Buckets &buckets) { + for (const auto &bucketIter : buckets) { + const auto &bucketId = bucketIter.first; + const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix + bucketId; + + deleteHardLink(bucketFilename); + createHardLink(bucketFilename + m_backupFilenameSuffix, bucketFilename); + } + + const auto &indexFilename = m_dbPath + m_indexFilename; + + deleteHardLink(indexFilename); + createHardLink(indexFilename + m_backupFilenameSuffix, indexFilename); +} + +void Integrity::deleteBackupHardLinks(const Buckets &buckets) { + for (const auto &bucketIter : buckets) { + const auto &bucketId = bucketIter.first; + const auto &bucketFilename = m_dbPath + m_bucketFilenamePrefix + + bucketId + m_backupFilenameSuffix; + + deleteHardLink(bucketFilename); + } + + deleteHardLink(m_dbPath + m_indexFilename + m_backupFilenameSuffix); +} + +void Integrity::createHardLink(const std::string &oldName, const std::string &newName) { + int ret = link(oldName.c_str(), newName.c_str()); + + if (ret < 0) { + int err = errno; + throw UnexpectedErrorException(err, strerror(err)); + LOGN("Trying to link to non-existent file: <%s>", oldName.c_str()); + } +} + +void Integrity::deleteHardLink(const std::string &filename) { + int ret = unlink(filename.c_str()); + + if (ret < 0) { + int err = errno; + if (err != ENOENT) { + LOGE("'unlink' function error [%d] : <%s>", err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } else { + LOGN("Trying to unlink non-existent file: <%s>", filename.c_str()); + } + } +} + +} /* namespace Cynara */ diff --git a/src/storage/Integrity.h b/src/storage/Integrity.h new file mode 100644 index 0000000..4b677b0 --- /dev/null +++ b/src/storage/Integrity.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/storage/Integrity.h + * @author Pawel Wieczorek + * @version 0.1 + * @brief Headers for Cynara::Integrity + */ + +#ifndef SRC_STORAGE_INTEGRITY_H_ +#define SRC_STORAGE_INTEGRITY_H_ + +#include +#include + +#include + +namespace Cynara { + +class Integrity +{ +public: + typedef std::function BucketPresenceTester; + Integrity(const std::string &path, const std::string &index, const std::string &backupSuffix, + const std::string &bucketPrefix) + : m_dbPath(path), m_indexFilename(index), m_backupFilenameSuffix(backupSuffix), + m_bucketFilenamePrefix(bucketPrefix) { + } + virtual ~Integrity() {}; + + virtual bool backupGuardExists(void) const; + virtual void createBackupGuard(void) const; + virtual void syncDatabase(const Buckets &buckets, bool syncBackup); + virtual void revalidatePrimaryDatabase(const Buckets &buckets); + virtual void deleteNonIndexedFiles(BucketPresenceTester tester); + +protected: + static void syncElement(const std::string &filename, int flags = O_RDONLY, + mode_t mode = S_IRUSR | S_IWUSR); + static void syncDirectory(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR); + + void createPrimaryHardLinks(const Buckets &buckets); + void deleteBackupHardLinks(const Buckets &buckets); + + static void createHardLink(const std::string &oldName, const std::string &newName); + static void deleteHardLink(const std::string &filename); + +private: + const std::string m_dbPath; + const std::string m_indexFilename; + const std::string m_backupFilenameSuffix; + const std::string m_bucketFilenamePrefix; + static const std::string m_guardFilename; +}; + +} // namespace Cynara + +#endif /* SRC_STORAGE_INTEGRITY_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ffddd87..063098f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,6 +32,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/helpers/creds-commons/creds-commons.cpp ${CYNARA_SRC}/storage/BucketDeserializer.cpp ${CYNARA_SRC}/storage/InMemoryStorageBackend.cpp + ${CYNARA_SRC}/storage/Integrity.cpp ${CYNARA_SRC}/storage/Storage.cpp ${CYNARA_SRC}/storage/StorageDeserializer.cpp ${CYNARA_SRC}/storage/StorageSerializer.cpp diff --git a/test/db/db6/_ b/test/db/db6/_ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db6/_additional b/test/db/db6/_additional new file mode 100644 index 0000000..cbeab67 --- /dev/null +++ b/test/db/db6/_additional @@ -0,0 +1 @@ +client1;user1;privilege1;0x0; diff --git a/test/db/db6/_additional~ b/test/db/db6/_additional~ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db6/_~ b/test/db/db6/_~ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db6/buckets b/test/db/db6/buckets new file mode 100644 index 0000000..19d7a93 --- /dev/null +++ b/test/db/db6/buckets @@ -0,0 +1,2 @@ +;0x0 +additional;0xFFFF diff --git a/test/db/db6/buckets~ b/test/db/db6/buckets~ new file mode 100644 index 0000000..19d7a93 --- /dev/null +++ b/test/db/db6/buckets~ @@ -0,0 +1,2 @@ +;0x0 +additional;0xFFFF diff --git a/test/db/db6/guard b/test/db/db6/guard new file mode 100644 index 0000000..e69de29 diff --git a/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h b/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h index 1c80dea..52b4fe3 100644 --- a/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h +++ b/test/storage/inmemorystoragebackend/fakeinmemorystoragebackend.h @@ -29,7 +29,7 @@ class FakeInMemoryStorageBackend : public Cynara::InMemoryStorageBackend { public: using Cynara::InMemoryStorageBackend::InMemoryStorageBackend; - MOCK_METHOD0(buckets, Cynara::Buckets&()); + MOCK_METHOD0(buckets, Cynara::Buckets&(void)); }; diff --git a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h index 3f08dea..2ec2920 100644 --- a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h +++ b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h @@ -67,6 +67,8 @@ protected: // TODO: consider defaulting accessor with ON_CALL Cynara::Buckets m_buckets; + static const std::string m_indexFileName; + static const std::string m_backupFileNameSuffix; }; diff --git a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp index 11c0968..c0fd640 100644 --- a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp +++ b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp @@ -40,6 +40,9 @@ using namespace Cynara; +const std::string InMemeoryStorageBackendFixture::m_indexFileName = "buckets"; +const std::string InMemeoryStorageBackendFixture::m_backupFileNameSuffix = "~"; + TEST_F(InMemeoryStorageBackendFixture, defaultPolicyIsDeny) { using ::testing::ReturnRef; @@ -192,7 +195,7 @@ TEST_F(InMemeoryStorageBackendFixture, deletePolicyFromNonexistentBucket) { // Database dir is empty TEST_F(InMemeoryStorageBackendFixture, load_no_db) { using ::testing::ReturnRef; - auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db1/"; + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/empty_db/"; FakeInMemoryStorageBackend backend(testDbPath); EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); backend.load(); @@ -252,3 +255,36 @@ TEST_F(InMemeoryStorageBackendFixture, second_bucket_corrupted) { backend.load(); ASSERT_DB_VIRGIN(m_buckets); } + +/** + * @brief Database was corrupted, restore from backup (which is present) + * @test Scenario: + * - There still is guard file in earlier prepared Cynara's policy database directory (db6) + * - Execution of load() should use backup files (present, with different contents than primaries) + * - Loaded database is checked - backup files were empty, so should recently loaded policies + */ +TEST_F(InMemeoryStorageBackendFixture, load_from_backup) { + using ::testing::ReturnRef; + using ::testing::IsEmpty; + using ::testing::InSequence; + + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db6/"; + FakeInMemoryStorageBackend backend(testDbPath); + + { + // Calls are expected in a specific order + InSequence s; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + } + + std::vector bucketIds = { "", "additional" }; + for(const auto &bucketId : bucketIds) { + SCOPED_TRACE(bucketId); + const auto bucketIter = m_buckets.find(bucketId); + ASSERT_NE(m_buckets.end(), bucketIter); + + const auto &bucketPolicies = bucketIter->second; + ASSERT_THAT(bucketPolicies, IsEmpty()); + } +} -- 2.7.4 From d1b33eecd1065cf626efc5380dcfc2da6a7c1359 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Thu, 13 Nov 2014 12:07:20 +0100 Subject: [PATCH 02/16] Ensure creation of minimal database This patch changes default behaviour of migration tool during package upgrade. Previously, Cynara's state path was left untouched. Now creation of minimal database is ensured. No changes are made if it already existed. Change-Id: I25158aec7d7b436ac1446d43277afe1337bfe4e5 --- migration/cynara-db-migration.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/migration/cynara-db-migration.sh b/migration/cynara-db-migration.sh index 0cf5edd..8cbebbf 100644 --- a/migration/cynara-db-migration.sh +++ b/migration/cynara-db-migration.sh @@ -94,9 +94,10 @@ migrate_db() { failure fi - : - # : is a null command, as functions may not be empty. - # Actual body will be added if database structure changes. + # Create minimal database if there was none: + if [ ! -d "${STATE_PATH}/${DB_DIR}" ]; then + create_db + fi } remove_db() { -- 2.7.4 From 8dd72120e13a4192408b8940b85ef40d980a3fdd Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 13 Nov 2014 14:25:56 +0100 Subject: [PATCH 03/16] Fix segfault in dump_buckets test Change-Id: If614900c9710dc0600c48622051afb484709155f --- test/storage/serializer/serialize.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/storage/serializer/serialize.cpp b/test/storage/serializer/serialize.cpp index cceed78..938283d 100644 --- a/test/storage/serializer/serialize.cpp +++ b/test/storage/serializer/serialize.cpp @@ -48,8 +48,8 @@ public: // Fake StorageSerializer for Cynara::PolicyBucket class FakeStorageSerializer : public Cynara::StorageSerializer { public: - FakeStorageSerializer() : Cynara::StorageSerializer(outStream), - outStream(new std::ostringstream()) {} + FakeStorageSerializer(std::shared_ptr o) : Cynara::StorageSerializer(o), + outStream(o) {} MOCK_METHOD1(dump, void(const Cynara::PolicyBucket &bucket)); std::shared_ptr outStream; }; @@ -82,7 +82,8 @@ TEST_F(StorageSerializerFixture, dump_buckets) { using ::testing::UnorderedElementsAreArray; // Will be returned as serializer for buckets - auto fakeBucketSerializer = std::make_shared(); + auto fakeBucketSerializer = std::make_shared( + std::make_shared()); buckets = { { "bucket1", PolicyBucket("bucket1", PredefinedPolicyType::DENY) }, -- 2.7.4 From 656f1a804ecf28619a0f7ea91ce26b43d27ec075 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Wed, 12 Nov 2014 16:30:35 +0100 Subject: [PATCH 04/16] Remove unnecessary Protocol shared pointers ProtocolFramePtr and ProtocolFrameHeaderPtr was used unnecessary (no shared ownership required). Change-Id: I71d4bf797450a46bc35e2321ff8d01a6508bcf88 --- src/common/protocol/ProtocolAdmin.cpp | 76 ++++++++++++------------- src/common/protocol/ProtocolClient.cpp | 26 ++++----- src/common/protocol/ProtocolFrame.cpp | 4 +- src/common/protocol/ProtocolFrame.h | 8 +-- src/common/protocol/ProtocolFrameHeader.h | 2 - src/common/protocol/ProtocolFrameSerializer.cpp | 16 +++--- src/common/protocol/ProtocolFrameSerializer.h | 4 +- 7 files changed, 66 insertions(+), 70 deletions(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 7d7d0f9..ca17e34 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -228,14 +228,14 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckRequestPtr requ request->key().user().value().c_str(), request->key().privilege().value().c_str(), request->startBucket().c_str(), request->recursive()); - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpAdminCheckRequest); - ProtocolSerialization::serialize(*frame, request->key().client().value()); - ProtocolSerialization::serialize(*frame, request->key().user().value()); - ProtocolSerialization::serialize(*frame, request->key().privilege().value()); - ProtocolSerialization::serialize(*frame, request->startBucket()); - ProtocolSerialization::serialize(*frame, request->recursive()); + ProtocolSerialization::serialize(frame, OpAdminCheckRequest); + ProtocolSerialization::serialize(frame, request->key().client().value()); + ProtocolSerialization::serialize(frame, request->key().user().value()); + ProtocolSerialization::serialize(frame, request->key().privilege().value()); + ProtocolSerialization::serialize(frame, request->startBucket()); + ProtocolSerialization::serialize(frame, request->recursive()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } @@ -246,12 +246,12 @@ void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketReque request->bucketId().c_str(), request->result().policyType(), request->result().metadata().c_str()); - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpInsertOrUpdateBucket); - ProtocolSerialization::serialize(*frame, request->bucketId()); - ProtocolSerialization::serialize(*frame, request->result().policyType()); - ProtocolSerialization::serialize(*frame, request->result().metadata()); + ProtocolSerialization::serialize(frame, OpInsertOrUpdateBucket); + ProtocolSerialization::serialize(frame, request->bucketId()); + ProtocolSerialization::serialize(frame, request->result().policyType()); + ProtocolSerialization::serialize(frame, request->result().metadata()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } @@ -260,10 +260,10 @@ void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr re LOGD("Serializing RemoveBucketRequest: sequenceNumber [%" PRIu16 "], bucketId <%s>", request->sequenceNumber(), request->bucketId().c_str()); - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpRemoveBucket); - ProtocolSerialization::serialize(*frame, request->bucketId()); + ProtocolSerialization::serialize(frame, OpRemoveBucket); + ProtocolSerialization::serialize(frame, request->bucketId()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } @@ -273,39 +273,39 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req "insertOrUpdate count [%zu], remove count [%zu]", request->sequenceNumber(), request->policiesToBeInsertedOrUpdated().size(), request->policiesToBeRemoved().size()); - ProtocolFramePtr frame = + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpSetPolicies); + ProtocolSerialization::serialize(frame, OpSetPolicies); - ProtocolSerialization::serialize(*frame, + ProtocolSerialization::serialize(frame, static_cast(request->policiesToBeInsertedOrUpdated().size())); for (auto policyBucket : request->policiesToBeInsertedOrUpdated()) { - ProtocolSerialization::serialize(*frame, policyBucket.first); - ProtocolSerialization::serialize(*frame, + ProtocolSerialization::serialize(frame, policyBucket.first); + ProtocolSerialization::serialize(frame, static_cast(policyBucket.second.size())); for (auto policy : policyBucket.second) { // PolicyKey - ProtocolSerialization::serialize(*frame, policy.key().client().value()); - ProtocolSerialization::serialize(*frame, policy.key().user().value()); - ProtocolSerialization::serialize(*frame, policy.key().privilege().value()); + ProtocolSerialization::serialize(frame, policy.key().client().value()); + ProtocolSerialization::serialize(frame, policy.key().user().value()); + ProtocolSerialization::serialize(frame, policy.key().privilege().value()); // PolicyResult - ProtocolSerialization::serialize(*frame, policy.result().policyType()); - ProtocolSerialization::serialize(*frame, policy.result().metadata()); + ProtocolSerialization::serialize(frame, policy.result().policyType()); + ProtocolSerialization::serialize(frame, policy.result().metadata()); } } - ProtocolSerialization::serialize(*frame, + ProtocolSerialization::serialize(frame, static_cast(request->policiesToBeRemoved().size())); for (auto policyBucket : request->policiesToBeRemoved()) { - ProtocolSerialization::serialize(*frame, policyBucket.first); - ProtocolSerialization::serialize(*frame, + ProtocolSerialization::serialize(frame, policyBucket.first); + ProtocolSerialization::serialize(frame, static_cast(policyBucket.second.size())); for (auto policyKey : policyBucket.second) { // PolicyKey - ProtocolSerialization::serialize(*frame, policyKey.client().value()); - ProtocolSerialization::serialize(*frame, policyKey.user().value()); - ProtocolSerialization::serialize(*frame, policyKey.privilege().value()); + ProtocolSerialization::serialize(frame, policyKey.client().value()); + ProtocolSerialization::serialize(frame, policyKey.user().value()); + ProtocolSerialization::serialize(frame, policyKey.privilege().value()); } } @@ -318,12 +318,12 @@ void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response response->sequenceNumber(), response->m_resultRef.policyType(), response->m_resultRef.metadata().c_str()); - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( response->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpCheckPolicyResponse); - ProtocolSerialization::serialize(*frame, response->m_resultRef.policyType()); - ProtocolSerialization::serialize(*frame, response->m_resultRef.metadata()); + ProtocolSerialization::serialize(frame, OpCheckPolicyResponse); + ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); + ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } @@ -332,11 +332,11 @@ void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) LOGD("Serializing CodeResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " "code [%" PRIu16 "]", OpCodeResponse, response->sequenceNumber(), response->m_code); - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( response->sequenceNumber()); - ProtocolSerialization::serialize(*frame, OpCodeResponse); - ProtocolSerialization::serialize(*frame, static_cast(response->m_code)); + ProtocolSerialization::serialize(frame, OpCodeResponse); + ProtocolSerialization::serialize(frame, static_cast(response->m_code)); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp index 94811dd..c643789 100644 --- a/src/common/protocol/ProtocolClient.cpp +++ b/src/common/protocol/ProtocolClient.cpp @@ -141,52 +141,52 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) } void ProtocolClient::execute(RequestContextPtr context, CancelRequestPtr request) { - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); LOGD("Serializing CancelRequest op [%" PRIu8 "]", OpCancelRequest); - ProtocolSerialization::serialize(*frame, OpCancelRequest); + ProtocolSerialization::serialize(frame, OpCancelRequest); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) { - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); LOGD("Serializing CheckRequest: client <%s>, user <%s>, privilege <%s>", request->key().client().value().c_str(), request->key().user().value().c_str(), request->key().privilege().value().c_str()); - ProtocolSerialization::serialize(*frame, OpCheckPolicyRequest); - ProtocolSerialization::serialize(*frame, request->key().client().value()); - ProtocolSerialization::serialize(*frame, request->key().user().value()); - ProtocolSerialization::serialize(*frame, request->key().privilege().value()); + ProtocolSerialization::serialize(frame, OpCheckPolicyRequest); + ProtocolSerialization::serialize(frame, request->key().client().value()); + ProtocolSerialization::serialize(frame, request->key().user().value()); + ProtocolSerialization::serialize(frame, request->key().privilege().value()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr response) { - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( response->sequenceNumber()); LOGD("Serializing CancelResponse: op [%" PRIu8 "]", OpCancelResponse); - ProtocolSerialization::serialize(*frame, OpCancelResponse); + ProtocolSerialization::serialize(frame, OpCancelResponse); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) { - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( response->sequenceNumber()); LOGD("Serializing CheckResponse: op [%" PRIu8 "], policyType [%" PRIu16 "], metadata <%s>", OpCheckPolicyResponse, response->m_resultRef.policyType(), response->m_resultRef.metadata().c_str()); - ProtocolSerialization::serialize(*frame, OpCheckPolicyResponse); - ProtocolSerialization::serialize(*frame, response->m_resultRef.policyType()); - ProtocolSerialization::serialize(*frame, response->m_resultRef.metadata()); + ProtocolSerialization::serialize(frame, OpCheckPolicyResponse); + ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); + ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } diff --git a/src/common/protocol/ProtocolFrame.cpp b/src/common/protocol/ProtocolFrame.cpp index 560217e..736be30 100644 --- a/src/common/protocol/ProtocolFrame.cpp +++ b/src/common/protocol/ProtocolFrame.cpp @@ -28,7 +28,7 @@ namespace Cynara { -ProtocolFrame::ProtocolFrame(ProtocolFrameHeaderPtr frameHeader, BinaryQueuePtr data) : +ProtocolFrame::ProtocolFrame(ProtocolFrameHeader frameHeader, BinaryQueuePtr data) : m_frameHeader(frameHeader), m_frameBodyContent(data) { } @@ -38,7 +38,7 @@ void ProtocolFrame::read(size_t num, void *bytes) { void ProtocolFrame::write(size_t num, const void *bytes) { m_frameBodyContent->appendCopy(bytes, num); - m_frameHeader->increaseFrameLength(num); + m_frameHeader.increaseFrameLength(num); } } /* namespace Cynara */ diff --git a/src/common/protocol/ProtocolFrame.h b/src/common/protocol/ProtocolFrame.h index 3d85cc0..73f22e9 100644 --- a/src/common/protocol/ProtocolFrame.h +++ b/src/common/protocol/ProtocolFrame.h @@ -39,10 +39,10 @@ class ProtocolFrameSerializer; class ProtocolFrame: public IStream { public: - ProtocolFrame(ProtocolFrameHeaderPtr frameHeader, BinaryQueuePtr headerContent); + ProtocolFrame(ProtocolFrameHeader frameHeader, BinaryQueuePtr headerContent); virtual ~ProtocolFrame() {}; - ProtocolFrameHeaderPtr frameHeader(void) { + ProtocolFrameHeader &frameHeader(void) { return m_frameHeader; } @@ -50,7 +50,7 @@ public: virtual void write(size_t num, const void *bytes); private: - ProtocolFrameHeaderPtr m_frameHeader; + ProtocolFrameHeader m_frameHeader; BinaryQueuePtr m_frameBodyContent; BinaryQueue &bodyContent(void) { @@ -60,8 +60,6 @@ private: friend class ProtocolFrameSerializer; }; -typedef std::shared_ptr ProtocolFramePtr; - } /* namespace Cynara */ #endif /* SRC_COMMON_PROTOCOL_PROTOCOLFRAME_H_ */ diff --git a/src/common/protocol/ProtocolFrameHeader.h b/src/common/protocol/ProtocolFrameHeader.h index ff92bf9..7b85465 100644 --- a/src/common/protocol/ProtocolFrameHeader.h +++ b/src/common/protocol/ProtocolFrameHeader.h @@ -107,8 +107,6 @@ private: friend class ProtocolFrameSerializer; }; -typedef std::shared_ptr ProtocolFrameHeaderPtr; - } /* namespace Cynara */ #endif /* SRC_COMMON_PROTOCOL_PROTOCOLFRAMEHEADER_H_ */ diff --git a/src/common/protocol/ProtocolFrameSerializer.cpp b/src/common/protocol/ProtocolFrameSerializer.cpp index 88a07d3..0599f02 100644 --- a/src/common/protocol/ProtocolFrameSerializer.cpp +++ b/src/common/protocol/ProtocolFrameSerializer.cpp @@ -65,19 +65,19 @@ void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader } } -ProtocolFramePtr ProtocolFrameSerializer::startSerialization(ProtocolFrameSequenceNumber sequenceNumber) { +ProtocolFrame ProtocolFrameSerializer::startSerialization(ProtocolFrameSequenceNumber sequenceNumber) { LOGD("Serialization started"); BinaryQueuePtr headerQueue = std::make_shared(); BinaryQueuePtr bodyQueue = std::make_shared(); - ProtocolFrameHeaderPtr header = std::make_shared(headerQueue); - header->setSequenceNumber(sequenceNumber); - header->increaseFrameLength(ProtocolFrameHeader::frameHeaderLength()); - return std::make_shared(header, bodyQueue); + ProtocolFrameHeader header(headerQueue); + header.setSequenceNumber(sequenceNumber); + header.increaseFrameLength(ProtocolFrameHeader::frameHeaderLength()); + return ProtocolFrame(header, bodyQueue); } -void ProtocolFrameSerializer::finishSerialization(ProtocolFramePtr frame, BinaryQueue &data) { - ProtocolFrameHeader &frameHeader = *frame->frameHeader(); +void ProtocolFrameSerializer::finishSerialization(ProtocolFrame &frame, BinaryQueue &data) { + ProtocolFrameHeader &frameHeader = frame.frameHeader(); ProtocolSerialization::serializeNoSize(frameHeader, ProtocolFrameHeader::m_signature); ProtocolSerialization::serialize(frameHeader, frameHeader.m_frameLength); ProtocolSerialization::serialize(frameHeader, frameHeader.m_sequenceNumber); @@ -87,7 +87,7 @@ void ProtocolFrameSerializer::finishSerialization(ProtocolFramePtr frame, Binary (int)frameHeader.m_sequenceNumber); data.appendMoveFrom(frameHeader.headerContent()); - data.appendMoveFrom(frame->bodyContent()); + data.appendMoveFrom(frame.bodyContent()); } } /* namespace Cynara */ diff --git a/src/common/protocol/ProtocolFrameSerializer.h b/src/common/protocol/ProtocolFrameSerializer.h index 8961e14..f2e201e 100644 --- a/src/common/protocol/ProtocolFrameSerializer.h +++ b/src/common/protocol/ProtocolFrameSerializer.h @@ -34,8 +34,8 @@ class ProtocolFrameSerializer { public: static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueue &data); - static ProtocolFramePtr startSerialization(ProtocolFrameSequenceNumber sequenceNumber); - static void finishSerialization(ProtocolFramePtr frame, BinaryQueue &data); + static ProtocolFrame startSerialization(ProtocolFrameSequenceNumber sequenceNumber); + static void finishSerialization(ProtocolFrame &frame, BinaryQueue &data); }; } /* namespace Cynara */ -- 2.7.4 From 481d3058557b53ed807fce6ba6412da683e0f392 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Wed, 12 Nov 2014 17:07:55 +0100 Subject: [PATCH 05/16] Reorganize ProtocolAdmin and ProtocolClient Private methods of ProtocolAdmin and ProtocolClient lost an argument, which was used only to pass member value from the same class. Change-Id: I5657d38cf9ccd47892082479eeae92d62f894227 --- src/common/protocol/ProtocolAdmin.cpp | 90 +++++++++++++++++----------------- src/common/protocol/ProtocolAdmin.h | 12 ++--- src/common/protocol/ProtocolClient.cpp | 34 ++++++------- src/common/protocol/ProtocolClient.h | 8 +-- 4 files changed, 73 insertions(+), 71 deletions(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index ca17e34..2d4c879 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -50,53 +50,54 @@ ProtocolPtr ProtocolAdmin::clone(void) { return std::make_shared(); } -RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(void) { std::string clientId, userId, privilegeId; PolicyBucketId startBucket; bool recursive; - ProtocolDeserialization::deserialize(frame, clientId); - ProtocolDeserialization::deserialize(frame, userId); - ProtocolDeserialization::deserialize(frame, privilegeId); - ProtocolDeserialization::deserialize(frame, startBucket); - ProtocolDeserialization::deserialize(frame, recursive); + ProtocolDeserialization::deserialize(m_frameHeader, clientId); + ProtocolDeserialization::deserialize(m_frameHeader, userId); + ProtocolDeserialization::deserialize(m_frameHeader, privilegeId); + ProtocolDeserialization::deserialize(m_frameHeader, startBucket); + ProtocolDeserialization::deserialize(m_frameHeader, recursive); LOGD("Deserialized AdminCheckRequest: clientId <%s>, userId <%s>, privilegeId <%s>, " "startBucket <%s>, recursive [%d]", clientId.c_str(), userId.c_str(), privilegeId.c_str(), startBucket.c_str(), recursive); return std::make_shared(PolicyKey(clientId, userId, privilegeId), - startBucket, recursive, frame.sequenceNumber()); + startBucket, recursive, + m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(void) { PolicyBucketId policyBucketId; PolicyType policyType; PolicyResult::PolicyMetadata policyMetaData; - ProtocolDeserialization::deserialize(frame, policyBucketId); - ProtocolDeserialization::deserialize(frame, policyType); - ProtocolDeserialization::deserialize(frame, policyMetaData); + ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId); + ProtocolDeserialization::deserialize(m_frameHeader, policyType); + ProtocolDeserialization::deserialize(m_frameHeader, policyMetaData); LOGD("Deserialized InsertOrUpdateBucketRequest: bucketId <%s>, " "result.type [%" PRIu16 "], result.meta <%s>", policyBucketId.c_str(), policyType, policyMetaData.c_str()); return std::make_shared(policyBucketId, - PolicyResult(policyType, policyMetaData), frame.sequenceNumber()); + PolicyResult(policyType, policyMetaData), m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(void) { PolicyBucketId policyBucketId; - ProtocolDeserialization::deserialize(frame, policyBucketId); + ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId); LOGD("Deserialized RemoveBucketRequest: bucketId <%s>", policyBucketId.c_str()); - return std::make_shared(policyBucketId, frame.sequenceNumber()); + return std::make_shared(policyBucketId, m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(void) { ProtocolFrameFieldsCount toBeInsertedOrUpdatedCount, toBeRemovedCount; ProtocolFrameFieldsCount policyCount; PolicyKeyFeature::ValueType clientId, user, privilege; @@ -105,19 +106,19 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra std::map> toBeInsertedOrUpdatedPolicies; std::map> toBeRemovedPolicies; - ProtocolDeserialization::deserialize(frame, toBeInsertedOrUpdatedCount); + ProtocolDeserialization::deserialize(m_frameHeader, toBeInsertedOrUpdatedCount); for (ProtocolFrameFieldsCount b = 0; b < toBeInsertedOrUpdatedCount; ++b) { PolicyBucketId policyBucketId; - ProtocolDeserialization::deserialize(frame, policyBucketId); - ProtocolDeserialization::deserialize(frame, policyCount); + ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId); + ProtocolDeserialization::deserialize(m_frameHeader, policyCount); for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) { // PolicyKey - ProtocolDeserialization::deserialize(frame, clientId); - ProtocolDeserialization::deserialize(frame, user); - ProtocolDeserialization::deserialize(frame, privilege); + ProtocolDeserialization::deserialize(m_frameHeader, clientId); + ProtocolDeserialization::deserialize(m_frameHeader, user); + ProtocolDeserialization::deserialize(m_frameHeader, privilege); // PolicyResult - ProtocolDeserialization::deserialize(frame, policyType); - ProtocolDeserialization::deserialize(frame, metadata); + ProtocolDeserialization::deserialize(m_frameHeader, policyType); + ProtocolDeserialization::deserialize(m_frameHeader, metadata); toBeInsertedOrUpdatedPolicies[policyBucketId].push_back( Policy(PolicyKey(clientId, user, privilege), @@ -125,16 +126,16 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra } } - ProtocolDeserialization::deserialize(frame, toBeRemovedCount); + ProtocolDeserialization::deserialize(m_frameHeader, toBeRemovedCount); for (ProtocolFrameFieldsCount b = 0; b < toBeRemovedCount; ++b) { PolicyBucketId policyBucketId; - ProtocolDeserialization::deserialize(frame, policyBucketId); - ProtocolDeserialization::deserialize(frame, policyCount); + ProtocolDeserialization::deserialize(m_frameHeader, policyBucketId); + ProtocolDeserialization::deserialize(m_frameHeader, policyCount); for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) { // PolicyKey - ProtocolDeserialization::deserialize(frame, clientId); - ProtocolDeserialization::deserialize(frame, user); - ProtocolDeserialization::deserialize(frame, privilege); + ProtocolDeserialization::deserialize(m_frameHeader, clientId); + ProtocolDeserialization::deserialize(m_frameHeader, user); + ProtocolDeserialization::deserialize(m_frameHeader, privilege); toBeRemovedPolicies[policyBucketId].push_back(PolicyKey(clientId, user, privilege)); } @@ -144,7 +145,8 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &fra "remove count [%" PRIu16 "]", toBeInsertedOrUpdatedCount, toBeRemovedCount); return std::make_shared(toBeInsertedOrUpdatedPolicies, - toBeRemovedPolicies, frame.sequenceNumber()); + toBeRemovedPolicies, + m_frameHeader.sequenceNumber()); } RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) { @@ -158,13 +160,13 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) { LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { case OpAdminCheckRequest: - return deserializeAdminCheckRequest(m_frameHeader); + return deserializeAdminCheckRequest(); case OpInsertOrUpdateBucket: - return deserializeInsertOrUpdateBucketRequest(m_frameHeader); + return deserializeInsertOrUpdateBucketRequest(); case OpRemoveBucket: - return deserializeRemoveBucketRequest(m_frameHeader); + return deserializeRemoveBucketRequest(); case OpSetPolicies: - return deserializeSetPoliciesRequest(m_frameHeader); + return deserializeSetPoliciesRequest(); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; @@ -174,29 +176,29 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) { return nullptr; } -ResponsePtr ProtocolAdmin::deserializeCheckResponse(ProtocolFrameHeader &frame) { +ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) { PolicyType result; PolicyResult::PolicyMetadata additionalInfo; - ProtocolDeserialization::deserialize(frame, result); - ProtocolDeserialization::deserialize(frame, additionalInfo); + ProtocolDeserialization::deserialize(m_frameHeader, result); + ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); const PolicyResult policyResult(result, additionalInfo); LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>", policyResult.policyType(), policyResult.metadata().c_str()); - return std::make_shared(policyResult, frame.sequenceNumber()); + return std::make_shared(policyResult, m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolAdmin::deserializeCodeResponse(ProtocolFrameHeader &frame) { +ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) { ProtocolResponseCode responseCode; - ProtocolDeserialization::deserialize(frame, responseCode); + ProtocolDeserialization::deserialize(m_frameHeader, responseCode); LOGD("Deserialized CodeResponse: code [%" PRIu16 "], ", responseCode); return std::make_shared(static_cast(responseCode), - frame.sequenceNumber()); + m_frameHeader.sequenceNumber()); } ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) { @@ -210,9 +212,9 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) { LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { case OpCheckPolicyResponse: - return deserializeCheckResponse(m_frameHeader); + return deserializeCheckResponse(); case OpCodeResponse: - return deserializeCodeResponse(m_frameHeader); + return deserializeCodeResponse(); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 2d1e702..3f7fcc9 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -47,13 +47,13 @@ public: virtual void execute(RequestContextPtr context, CodeResponsePtr response); private: - RequestPtr deserializeAdminCheckRequest(ProtocolFrameHeader &frame); - RequestPtr deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame); - RequestPtr deserializeRemoveBucketRequest(ProtocolFrameHeader &frame); - RequestPtr deserializeSetPoliciesRequest(ProtocolFrameHeader &frame); + RequestPtr deserializeAdminCheckRequest(void); + RequestPtr deserializeInsertOrUpdateBucketRequest(void); + RequestPtr deserializeRemoveBucketRequest(void); + RequestPtr deserializeSetPoliciesRequest(void); - ResponsePtr deserializeCheckResponse(ProtocolFrameHeader &frame); - ResponsePtr deserializeCodeResponse(ProtocolFrameHeader &frame); + ResponsePtr deserializeCheckResponse(void); + ResponsePtr deserializeCodeResponse(void); }; } // namespace Cynara diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp index c643789..c130809 100644 --- a/src/common/protocol/ProtocolClient.cpp +++ b/src/common/protocol/ProtocolClient.cpp @@ -54,23 +54,23 @@ ProtocolPtr ProtocolClient::clone(void) { return std::make_shared(); } -RequestPtr ProtocolClient::deserializeCancelRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolClient::deserializeCancelRequest(void) { LOGD("Deserialized CancelRequest"); - return std::make_shared(frame.sequenceNumber()); + return std::make_shared(m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolClient::deserializeCheckRequest(ProtocolFrameHeader &frame) { +RequestPtr ProtocolClient::deserializeCheckRequest(void) { std::string clientId, userId, privilegeId; - ProtocolDeserialization::deserialize(frame, clientId); - ProtocolDeserialization::deserialize(frame, userId); - ProtocolDeserialization::deserialize(frame, privilegeId); + ProtocolDeserialization::deserialize(m_frameHeader, clientId); + ProtocolDeserialization::deserialize(m_frameHeader, userId); + ProtocolDeserialization::deserialize(m_frameHeader, privilegeId); LOGD("Deserialized CheckRequest: client <%s>, user <%s>, privilege <%s>", clientId.c_str(), userId.c_str(), privilegeId.c_str()); return std::make_shared(PolicyKey(clientId, userId, privilegeId), - frame.sequenceNumber()); + m_frameHeader.sequenceNumber()); } RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { @@ -85,9 +85,9 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { case OpCheckPolicyRequest: - return deserializeCheckRequest(m_frameHeader); + return deserializeCheckRequest(); case OpCancelRequest: - return deserializeCancelRequest(m_frameHeader); + return deserializeCancelRequest(); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; @@ -97,24 +97,24 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { return nullptr; } -ResponsePtr ProtocolClient::deserializeCancelResponse(ProtocolFrameHeader &frame) { +ResponsePtr ProtocolClient::deserializeCancelResponse(void) { LOGD("Deserialized CancelResponse"); - return std::make_shared(frame.sequenceNumber()); + return std::make_shared(m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolClient::deserializeCheckResponse(ProtocolFrameHeader &frame) { +ResponsePtr ProtocolClient::deserializeCheckResponse(void) { PolicyType result; PolicyResult::PolicyMetadata additionalInfo; - ProtocolDeserialization::deserialize(frame, result); - ProtocolDeserialization::deserialize(frame, additionalInfo); + ProtocolDeserialization::deserialize(m_frameHeader, result); + ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); const PolicyResult policyResult(result, additionalInfo); LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>", policyResult.policyType(), policyResult.metadata().c_str()); - return std::make_shared(policyResult, frame.sequenceNumber()); + return std::make_shared(policyResult, m_frameHeader.sequenceNumber()); } ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) { @@ -128,9 +128,9 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { case OpCheckPolicyResponse: - return deserializeCheckResponse(m_frameHeader); + return deserializeCheckResponse(); case OpCancelResponse: - return deserializeCancelResponse(m_frameHeader); + return deserializeCancelResponse(); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; diff --git a/src/common/protocol/ProtocolClient.h b/src/common/protocol/ProtocolClient.h index 1bb1b6a..dc72e7a 100644 --- a/src/common/protocol/ProtocolClient.h +++ b/src/common/protocol/ProtocolClient.h @@ -48,11 +48,11 @@ public: virtual void execute(RequestContextPtr context, CheckResponsePtr response); private: - RequestPtr deserializeCancelRequest(ProtocolFrameHeader &frame); - RequestPtr deserializeCheckRequest(ProtocolFrameHeader &frame); + RequestPtr deserializeCancelRequest(void); + RequestPtr deserializeCheckRequest(void); - ResponsePtr deserializeCancelResponse(ProtocolFrameHeader &frame); - ResponsePtr deserializeCheckResponse(ProtocolFrameHeader &frame); + ResponsePtr deserializeCancelResponse(void); + ResponsePtr deserializeCheckResponse(void); }; } // namespace Cynara -- 2.7.4 From cb00a4e9ea320a3f74cb28b06e30bb7b5e43d613 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Wed, 12 Nov 2014 16:36:52 +0100 Subject: [PATCH 06/16] Remove dangerous reference RequestContext contained reference to an external BinaryQueue. One problem was, BBQ was held inside vector (so practically any operation on vector made this object out-of-date), second problem was, RequestContext was passed to other classes inside shared_ptr, so owner of this bbq looses control other its reference. Moreover, soon RequestContext will be held pending (e.g. when waiting for external Agent to return answer) inside cynara logic, so BBQ stored inside RequestContext needs to be alive as long as corresponding connection is opened. Not more, not less. Change-Id: I79c9eb9b5e74927bd7bb159da01fae23612ca83e --- src/client-async/sockets/SocketClientAsync.cpp | 8 +-- src/client-async/sockets/SocketClientAsync.h | 4 +- src/common/containers/BinaryQueue.h | 67 ++++++++++++------------- src/common/exceptions/ContextErrorException.h | 42 ++++++++++++++++ src/common/protocol/Protocol.h | 4 +- src/common/protocol/ProtocolAdmin.cpp | 16 +++--- src/common/protocol/ProtocolAdmin.h | 4 +- src/common/protocol/ProtocolClient.cpp | 12 ++--- src/common/protocol/ProtocolClient.h | 4 +- src/common/protocol/ProtocolFrameSerializer.cpp | 8 +-- src/common/protocol/ProtocolFrameSerializer.h | 2 +- src/common/protocol/ProtocolSignal.cpp | 8 +-- src/common/protocol/ProtocolSignal.h | 4 +- src/common/request/RequestContext.h | 12 +++-- src/common/sockets/SocketClient.cpp | 6 ++- src/common/sockets/SocketClient.h | 4 +- src/service/sockets/Descriptor.cpp | 24 ++++++--- src/service/sockets/Descriptor.h | 26 +++++----- 18 files changed, 158 insertions(+), 97 deletions(-) create mode 100644 src/common/exceptions/ContextErrorException.h diff --git a/src/client-async/sockets/SocketClientAsync.cpp b/src/client-async/sockets/SocketClientAsync.cpp index e3ffbd4..148b13a 100644 --- a/src/client-async/sockets/SocketClientAsync.cpp +++ b/src/client-async/sockets/SocketClientAsync.cpp @@ -30,6 +30,8 @@ namespace Cynara { SocketClientAsync::SocketClientAsync(const std::string &socketPath, ProtocolPtr protocol) : m_socket(socketPath, 0), m_protocol(protocol) { + m_readQueue = std::make_shared(); + m_writeQueue = std::make_shared(); } Socket::ConnectionStatus SocketClientAsync::connect(void) { @@ -54,15 +56,15 @@ void SocketClientAsync::appendRequest(RequestPtr request) { } bool SocketClientAsync::isDataToSend(void) { - return m_socket.isDataToSend() || !m_writeQueue.empty(); + return m_socket.isDataToSend() || !m_writeQueue->empty(); } Socket::SendStatus SocketClientAsync::sendToCynara(void) { - return m_socket.sendToServer(m_writeQueue); + return m_socket.sendToServer(*m_writeQueue); } bool SocketClientAsync::receiveFromCynara(void) { - return m_socket.receiveFromServer(m_readQueue); + return m_socket.receiveFromServer(*m_readQueue); } ResponsePtr SocketClientAsync::getResponse(void) { diff --git a/src/client-async/sockets/SocketClientAsync.h b/src/client-async/sockets/SocketClientAsync.h index 5fb0543..eaacf84 100644 --- a/src/client-async/sockets/SocketClientAsync.h +++ b/src/client-async/sockets/SocketClientAsync.h @@ -56,8 +56,8 @@ public: private: Socket m_socket; ProtocolPtr m_protocol; - BinaryQueue m_readQueue; - BinaryQueue m_writeQueue; + BinaryQueuePtr m_readQueue; + BinaryQueuePtr m_writeQueue; }; } // namespace Cynara diff --git a/src/common/containers/BinaryQueue.h b/src/common/containers/BinaryQueue.h index f69f786..12b2e8a 100644 --- a/src/common/containers/BinaryQueue.h +++ b/src/common/containers/BinaryQueue.h @@ -33,52 +33,20 @@ namespace Cynara { */ class BinaryQueue; typedef std::shared_ptr BinaryQueuePtr; +typedef std::weak_ptr BinaryQueueWeakPtr; /** * Binary stream implemented as constant size bucket list * * @todo Add optimized implementation for FlattenConsume */ -class BinaryQueue -{ - public: +class BinaryQueue { +public: typedef void (*BufferDeleter)(const void *buffer, size_t bufferSize, void *userParam); static void bufferDeleterFree(const void *buffer, size_t bufferSize, void *userParam); - - private: - struct Bucket - { - const void *buffer; - const void *ptr; - size_t size; - size_t left; - - BufferDeleter deleter; - void *param; - - Bucket(const void *buffer, - size_t bufferSize, - BufferDeleter deleter, - void *userParam); - ~Bucket(); - // make it noncopyable - Bucket(const Bucket &) = delete; - const Bucket &operator=(const Bucket &) = delete; - // make it nonmoveable - Bucket(Bucket &&) = delete; - Bucket &operator=(Bucket &&) = delete; - }; - - typedef std::list BucketList; - BucketList m_buckets; - size_t m_size; - - static void deleteBucket(Bucket *bucket); - - public: /** * Construct empty binary queue */ @@ -239,6 +207,35 @@ class BinaryQueue * is larger than available bytes in binary queue */ void flattenConsume(void *buffer, size_t bufferSize); + +private: + struct Bucket { + const void *buffer; + const void *ptr; + size_t size; + size_t left; + + BufferDeleter deleter; + void *param; + + Bucket(const void *buffer, + size_t bufferSize, + BufferDeleter deleter, + void *userParam); + ~Bucket(); + // make it noncopyable + Bucket(const Bucket &) = delete; + const Bucket &operator=(const Bucket &) = delete; + // make it nonmoveable + Bucket(Bucket &&) = delete; + Bucket &operator=(Bucket &&) = delete; + }; + + typedef std::list BucketList; + BucketList m_buckets; + size_t m_size; + + static void deleteBucket(Bucket *bucket); }; } // namespace Cynara diff --git a/src/common/exceptions/ContextErrorException.h b/src/common/exceptions/ContextErrorException.h new file mode 100644 index 0000000..771065a --- /dev/null +++ b/src/common/exceptions/ContextErrorException.h @@ -0,0 +1,42 @@ +/* + * 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/ContextErrorException.h + * @author Zofia Abramowska + * @version 1.0 + * @brief Implementation of ContextErrorException.h + */ + +#ifndef SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_ + +#include "Exception.h" + +namespace Cynara { + +class ContextErrorException : public Exception { +public: + ContextErrorException() = default; + virtual ~ContextErrorException() {}; + + virtual const std::string message(void) const { + return "ContextErrorException"; + } +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_CONTEXTERROREXCEPTION_H_ */ diff --git a/src/common/protocol/Protocol.h b/src/common/protocol/Protocol.h index b98f145..63ee24d 100644 --- a/src/common/protocol/Protocol.h +++ b/src/common/protocol/Protocol.h @@ -44,8 +44,8 @@ public: virtual ProtocolPtr clone(void) = 0; - virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue) = 0; - virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue) = 0; + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue) = 0; + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue) = 0; ProtocolFrameHeader &frameHeader(void) { return m_frameHeader; diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 2d4c879..8d792f9 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -149,7 +149,7 @@ RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(void) { m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) { +RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); if (m_frameHeader.isFrameComplete()) { @@ -201,7 +201,7 @@ ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) { m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) { +ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); if (m_frameHeader.isFrameComplete()) { @@ -239,7 +239,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckRequestPtr requ ProtocolSerialization::serialize(frame, request->startBucket()); ProtocolSerialization::serialize(frame, request->recursive()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { @@ -255,7 +255,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketReque ProtocolSerialization::serialize(frame, request->result().policyType()); ProtocolSerialization::serialize(frame, request->result().metadata()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { @@ -267,7 +267,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr re ProtocolSerialization::serialize(frame, OpRemoveBucket); ProtocolSerialization::serialize(frame, request->bucketId()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { @@ -311,7 +311,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req } } - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) { @@ -327,7 +327,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) { @@ -340,7 +340,7 @@ void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) ProtocolSerialization::serialize(frame, OpCodeResponse); ProtocolSerialization::serialize(frame, static_cast(response->m_code)); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } } // namespace Cynara diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 3f7fcc9..9d2c6ac 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -35,8 +35,8 @@ public: virtual ProtocolPtr clone(void); - virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue); - virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue); + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp index c130809..3f13653 100644 --- a/src/common/protocol/ProtocolClient.cpp +++ b/src/common/protocol/ProtocolClient.cpp @@ -73,7 +73,7 @@ RequestPtr ProtocolClient::deserializeCheckRequest(void) { m_frameHeader.sequenceNumber()); } -RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { +RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); if (m_frameHeader.isFrameComplete()) { @@ -117,7 +117,7 @@ ResponsePtr ProtocolClient::deserializeCheckResponse(void) { return std::make_shared(policyResult, m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) { +ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); if (m_frameHeader.isFrameComplete()) { @@ -147,7 +147,7 @@ void ProtocolClient::execute(RequestContextPtr context, CancelRequestPtr request ProtocolSerialization::serialize(frame, OpCancelRequest); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) { @@ -162,7 +162,7 @@ void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) ProtocolSerialization::serialize(frame, request->key().user().value()); ProtocolSerialization::serialize(frame, request->key().privilege().value()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr response) { @@ -173,7 +173,7 @@ void ProtocolClient::execute(RequestContextPtr context, CancelResponsePtr respon ProtocolSerialization::serialize(frame, OpCancelResponse); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) { @@ -188,7 +188,7 @@ void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr respons ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); - ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } } // namespace Cynara diff --git a/src/common/protocol/ProtocolClient.h b/src/common/protocol/ProtocolClient.h index dc72e7a..a1c5110 100644 --- a/src/common/protocol/ProtocolClient.h +++ b/src/common/protocol/ProtocolClient.h @@ -38,8 +38,8 @@ public: virtual ProtocolPtr clone(void); - virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue); - virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue); + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); diff --git a/src/common/protocol/ProtocolFrameSerializer.cpp b/src/common/protocol/ProtocolFrameSerializer.cpp index 0599f02..68c497c 100644 --- a/src/common/protocol/ProtocolFrameSerializer.cpp +++ b/src/common/protocol/ProtocolFrameSerializer.cpp @@ -31,15 +31,15 @@ namespace Cynara { void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader, - BinaryQueue &data) { + BinaryQueuePtr data) { if (!frameHeader.isHeaderComplete()) { - if ((data.size() < ProtocolFrameHeader::frameHeaderLength())) { + if ((data->size() < ProtocolFrameHeader::frameHeaderLength())) { return; } LOGD("Deserializing frameHeader"); - frameHeader.setHeaderContent(BinaryQueuePtr(&data, [=] (BinaryQueue *) {})); + frameHeader.setHeaderContent(data); ProtocolFrameSignature signature; ProtocolDeserialization::deserialize(frameHeader, frameHeader.m_signature.length(), @@ -60,7 +60,7 @@ void ProtocolFrameSerializer::deserializeHeader(ProtocolFrameHeader &frameHeader frameHeader.setHeaderComplete(); } - if (data.size() >= (frameHeader.frameLength() - ProtocolFrameHeader::frameHeaderLength())) { + if (data->size() >= (frameHeader.frameLength() - ProtocolFrameHeader::frameHeaderLength())) { frameHeader.setBodyComplete(); } } diff --git a/src/common/protocol/ProtocolFrameSerializer.h b/src/common/protocol/ProtocolFrameSerializer.h index f2e201e..d7d6c15 100644 --- a/src/common/protocol/ProtocolFrameSerializer.h +++ b/src/common/protocol/ProtocolFrameSerializer.h @@ -33,7 +33,7 @@ namespace Cynara { class ProtocolFrameSerializer { public: - static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueue &data); + static void deserializeHeader(ProtocolFrameHeader &frameHeader, BinaryQueuePtr data); static ProtocolFrame startSerialization(ProtocolFrameSequenceNumber sequenceNumber); static void finishSerialization(ProtocolFrame &frame, BinaryQueue &data); }; diff --git a/src/common/protocol/ProtocolSignal.cpp b/src/common/protocol/ProtocolSignal.cpp index 963ee9a..d04dbbe 100644 --- a/src/common/protocol/ProtocolSignal.cpp +++ b/src/common/protocol/ProtocolSignal.cpp @@ -46,17 +46,17 @@ ProtocolPtr ProtocolSignal::clone(void) { return std::make_shared(); } -RequestPtr ProtocolSignal::extractRequestFromBuffer(BinaryQueue &bufferQueue) { - if (bufferQueue.size() >= sizeof(struct signalfd_siginfo)) { +RequestPtr ProtocolSignal::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { + if (bufferQueue->size() >= sizeof(struct signalfd_siginfo)) { struct signalfd_siginfo sigInfo; - bufferQueue.flattenConsume(&sigInfo, sizeof(sigInfo)); + bufferQueue->flattenConsume(&sigInfo, sizeof(sigInfo)); return std::make_shared(sigInfo); } return nullptr; } -ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueue &bufferQueue UNUSED) { +ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueuePtr bufferQueue UNUSED) { throw NotImplementedException(); } diff --git a/src/common/protocol/ProtocolSignal.h b/src/common/protocol/ProtocolSignal.h index e2142da..6c544c4 100644 --- a/src/common/protocol/ProtocolSignal.h +++ b/src/common/protocol/ProtocolSignal.h @@ -36,8 +36,8 @@ public: virtual ProtocolPtr clone(void); - virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue); - virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue); + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); virtual void execute(RequestContextPtr context, SignalRequestPtr request); }; diff --git a/src/common/request/RequestContext.h b/src/common/request/RequestContext.h index 33b6ef4..9c98bef 100644 --- a/src/common/request/RequestContext.h +++ b/src/common/request/RequestContext.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -36,10 +37,10 @@ namespace Cynara { class RequestContext { private: ResponseTakerWeakPtr m_responseTaker; - BinaryQueue &m_responseQueue; + BinaryQueueWeakPtr m_responseQueue; public: - RequestContext(ResponseTakerPtr responseTaker, BinaryQueue &responseQueue) + RequestContext(ResponseTakerPtr responseTaker, BinaryQueuePtr responseQueue) : m_responseTaker(responseTaker), m_responseQueue(responseQueue) { } @@ -49,8 +50,11 @@ public: response->execute(response, taker, self); } - BinaryQueue &responseQueue(void) const { - return m_responseQueue; + BinaryQueuePtr responseQueue(void) const { + auto bbqPtr = m_responseQueue.lock(); + if (bbqPtr) + return bbqPtr; + throw ContextErrorException(); } }; diff --git a/src/common/sockets/SocketClient.cpp b/src/common/sockets/SocketClient.cpp index 6db91d6..b3ce8ad 100644 --- a/src/common/sockets/SocketClient.cpp +++ b/src/common/sockets/SocketClient.cpp @@ -37,6 +37,8 @@ namespace Cynara { SocketClient::SocketClient(const std::string &socketPath, ProtocolPtr protocol) : m_socket(socketPath), m_protocol(protocol) { + m_writeQueue = std::make_shared(); + m_readQueue = std::make_shared(); } bool SocketClient::connect(void) { @@ -64,14 +66,14 @@ ResponsePtr SocketClient::askCynaraServer(RequestPtr request) { request->execute(request, m_protocol, context); //send request to cynara - if (m_socket.sendToServer(m_writeQueue) == Socket::SendStatus::CONNECTION_LOST) { + 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.receiveFromServer(m_readQueue)) { + if (!m_socket.receiveFromServer(*m_readQueue)) { LOGW("Disconnected while receiving response from Cynara."); return nullptr; } diff --git a/src/common/sockets/SocketClient.h b/src/common/sockets/SocketClient.h index 9f9737f..c313b13 100644 --- a/src/common/sockets/SocketClient.h +++ b/src/common/sockets/SocketClient.h @@ -41,8 +41,8 @@ class SocketClient { private: Socket m_socket; ProtocolPtr m_protocol; - BinaryQueue m_readQueue; - BinaryQueue m_writeQueue; + BinaryQueuePtr m_readQueue; + BinaryQueuePtr m_writeQueue; public: SocketClient(const std::string &socketPath, ProtocolPtr protocol); diff --git a/src/service/sockets/Descriptor.cpp b/src/service/sockets/Descriptor.cpp index 0e55e4b..b2e9459 100644 --- a/src/service/sockets/Descriptor.cpp +++ b/src/service/sockets/Descriptor.cpp @@ -27,8 +27,17 @@ namespace Cynara { Descriptor::Descriptor() : m_listen(false), m_used(false), m_client(false), m_protocol(nullptr) { } +void Descriptor::checkQueues(void) { + if (!m_writeQueue) + m_writeQueue = std::make_shared(); + if (!m_readQueue) + m_readQueue = std::make_shared(); +} + bool Descriptor::hasDataToWrite(void) const { - return !(m_writeQueue.empty() && m_writeBuffer.empty()); + if (m_writeQueue) + return !(m_writeQueue->empty() && m_writeBuffer.empty()); + return false; } ResponseTakerPtr Descriptor::responseTaker(void) const { @@ -36,19 +45,22 @@ ResponseTakerPtr Descriptor::responseTaker(void) const { } void Descriptor::pushReadBuffer(const RawBuffer &readbuffer) { - m_readQueue.appendCopy(readbuffer.data(), readbuffer.size()); + checkQueues(); + m_readQueue->appendCopy(readbuffer.data(), readbuffer.size()); } RequestPtr Descriptor::extractRequest(void) { + checkQueues(); return m_protocol->extractRequestFromBuffer(m_readQueue); } RawBuffer &Descriptor::prepareWriteBuffer(void) { - size_t queuedDataSize = m_writeQueue.size(); + checkQueues(); + size_t queuedDataSize = m_writeQueue->size(); size_t bufferDataSize = m_writeBuffer.size(); m_writeBuffer.resize(queuedDataSize + bufferDataSize); - m_writeQueue.flattenConsume(m_writeBuffer.data() + bufferDataSize, queuedDataSize); + m_writeQueue->flattenConsume(m_writeBuffer.data() + bufferDataSize, queuedDataSize); return m_writeBuffer; } @@ -57,8 +69,8 @@ void Descriptor::clear(void) { m_listen = false; m_used = false; m_client = false; - m_readQueue.clear(); - m_writeQueue.clear(); + m_readQueue.reset(); + m_writeQueue.reset(); m_writeBuffer.clear(); m_protocol.reset(); } diff --git a/src/service/sockets/Descriptor.h b/src/service/sockets/Descriptor.h index 0f42a36..5d77028 100644 --- a/src/service/sockets/Descriptor.h +++ b/src/service/sockets/Descriptor.h @@ -34,17 +34,6 @@ namespace Cynara { class Descriptor { -private: - bool m_listen; - bool m_used; - bool m_client; - - BinaryQueue m_readQueue; - BinaryQueue m_writeQueue; - RawBuffer m_writeBuffer; - - ProtocolPtr m_protocol; - public: Descriptor(); @@ -68,7 +57,7 @@ public: ResponseTakerPtr responseTaker(void) const; - BinaryQueue &writeQueue(void) { + BinaryQueuePtr writeQueue(void) { return m_writeQueue; } @@ -94,6 +83,19 @@ public: RawBuffer &prepareWriteBuffer(void); void clear(void); + +private: + bool m_listen; + bool m_used; + bool m_client; + + BinaryQueuePtr m_readQueue; + BinaryQueuePtr m_writeQueue; + RawBuffer m_writeBuffer; + + ProtocolPtr m_protocol; + + void checkQueues(void); }; } // namespace Cynara -- 2.7.4 From 86891d2550fcec655be8a7d4d53037a626c42b2d Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Fri, 14 Nov 2014 13:04:19 +0100 Subject: [PATCH 07/16] Disallow adding valid and invalid policies at once Storage::insertPolicies() now cares, if all buckets exist before it makes any change in database (in memory as well as in storage). No changes are made if any part of request contains invalid parameters. Change-Id: Ia8d180c7af88bd945dca22f2a4a41b049fdb4c33 --- src/storage/Storage.cpp | 6 ++++++ test/storage/storage/policies.cpp | 32 ++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/storage/Storage.cpp b/src/storage/Storage.cpp index 39793e2..aa9bc93 100644 --- a/src/storage/Storage.cpp +++ b/src/storage/Storage.cpp @@ -101,7 +101,13 @@ void Storage::insertPolicies(const std::map> // TODO: Rewrite, when transactions are supported // Check if all of buckets exist for (const auto &group : policiesByBucketId) { + const auto &bucketId = group.first; const auto &policies = group.second; + + if (m_backend.hasBucket(bucketId) == false) { + throw BucketNotExistsException(bucketId); + } + std::for_each(policies.cbegin(), policies.cend(), pointedBucketExists); } diff --git a/test/storage/storage/policies.cpp b/test/storage/storage/policies.cpp index 0166ff5..8d72dde 100644 --- a/test/storage/storage/policies.cpp +++ b/test/storage/storage/policies.cpp @@ -86,8 +86,12 @@ TEST(storage, insertPolicies) { FakeStorageBackend backend; Storage storage(backend); - PolicyBucketId testBucket1 = "test-bucket-1"; - PolicyBucketId testBucket2 = "test-bucket-2"; + std::vector testBuckets = { + PolicyBucketId("test-bucket-1"), + PolicyBucketId("test-bucket-2"), + }; + + PolicyResult defaultPolicy(PredefinedPolicyType::DENY); typedef std::pair> BucketPolicyPair; @@ -96,18 +100,26 @@ TEST(storage, insertPolicies) { }; std::map> policiesToInsert = { - BucketPolicyPair(testBucket1, { + BucketPolicyPair(testBuckets[0], { createPolicy("1", ALLOW), createPolicy("2", DENY), createPolicy("3", DENY) }), - BucketPolicyPair(testBucket2, { - createPolicy("4", { BUCKET, testBucket1 }), + BucketPolicyPair(testBuckets[1], { + createPolicy("4", { BUCKET, testBuckets[0] }), createPolicy("5", PredefinedPolicyType::ALLOW) }) }; - EXPECT_CALL(backend, hasBucket(testBucket1)).WillOnce(Return(true)); + for (const auto &bucket: testBuckets) { + EXPECT_CALL(backend, hasBucket(bucket)).WillOnce(Return(false)); + EXPECT_CALL(backend, createBucket(bucket, defaultPolicy)).WillOnce(Return()); + + storage.addOrUpdateBucket(bucket, defaultPolicy); + } + + EXPECT_CALL(backend, hasBucket(testBuckets[0])).WillRepeatedly(Return(true)); + EXPECT_CALL(backend, hasBucket(testBuckets[1])).WillOnce(Return(true)); for (const auto &group : policiesToInsert) { const auto &bucketId = group.first; @@ -130,6 +142,8 @@ TEST(storage, insertPointingToNonexistentBucket) { PolicyBucketId testBucketId = "test-bucket-1"; PolicyBucketId nonexistentBucketId = "nonexistent"; + PolicyResult defaultPolicy(PredefinedPolicyType::DENY); + typedef std::pair> BucketPolicyPair; auto createPolicy = [] (const std::string &keySuffix, const PolicyResult &result) -> Policy { @@ -143,6 +157,12 @@ TEST(storage, insertPointingToNonexistentBucket) { }), }; + EXPECT_CALL(backend, hasBucket(testBucketId)).WillOnce(Return(false)); + EXPECT_CALL(backend, createBucket(testBucketId, defaultPolicy)).WillOnce(Return()); + + storage.addOrUpdateBucket(testBucketId, defaultPolicy); + + EXPECT_CALL(backend, hasBucket(testBucketId)).WillOnce(Return(true)); EXPECT_CALL(backend, hasBucket(nonexistentBucketId)).WillOnce(Return(false)); ASSERT_THROW(storage.insertPolicies(policiesToInsert), BucketNotExistsException); -- 2.7.4 From 6013044e77d40a59b49043e82e47332cd69b6d3d Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 14 Nov 2014 14:29:31 +0100 Subject: [PATCH 08/16] Add context invalidation mechanism RequestTaker gets RequestContext, which might be processed in another event loop. During this loop socket associated with this context might get closed, so class holding this context needs notification. Change-Id: I77dee05b84a987e444f4ec71e87bcb867682768b --- src/common/request/RequestTaker.cpp | 4 ++++ src/common/request/RequestTaker.h | 2 ++ src/service/logic/Logic.cpp | 4 ++++ src/service/logic/Logic.h | 2 ++ src/service/sockets/SocketManager.cpp | 5 ++++- 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index c87a9a4..a4d7c2d 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -59,4 +59,8 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, SignalRequestPtr re throw NotImplementedException(); } +void RequestTaker::contextClosed(RequestContextPtr context UNUSED) { + throw NotImplementedException(); +} + } // namespace Cynara diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index b1d3466..522d8bb 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -39,6 +39,8 @@ public: virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, SignalRequestPtr request); + + virtual void contextClosed(RequestContextPtr context); }; } // namespace Cynara diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index f76ce98..ca56d64 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -174,6 +174,10 @@ void Logic::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { request->sequenceNumber())); } +void Logic::contextClosed(RequestContextPtr context UNUSED) { + //We don't care now, but we will +} + void Logic::onPoliciesChanged(void) { m_storage->save(); m_socketManager->disconnectAllClients(); diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index 3c434a5..e74cffe 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -64,6 +64,8 @@ public: virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, SignalRequestPtr request); + virtual void contextClosed(RequestContextPtr context); + private: PluginManagerPtr m_pluginManager; StoragePtr m_storage; diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index cb3c9b4..c9e1692 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -210,9 +210,12 @@ void SocketManager::readyForAccept(int fd) { void SocketManager::closeSocket(int fd) { LOGD("SocketManger closeSocket fd [%d] start", fd); + Descriptor &desc = m_fds[fd]; + requestTaker()->contextClosed(std::make_shared(nullptr, + desc.writeQueue())); removeReadSocket(fd); removeWriteSocket(fd); - m_fds[fd].clear(); + desc.clear(); close(fd); LOGD("SocketManger closeSocket fd [%d] done", fd); } -- 2.7.4 From 06da6ae48965239adbb1b104707f1dd893f8c316 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 17 Oct 2014 14:48:46 +0200 Subject: [PATCH 09/16] Add PathConfig Put all default paths into globally visible namespaces. Change-Id: I4f234c5558e828cbcacf86de8d266e89a0ad687c --- src/admin/logic/Logic.cpp | 4 +-- src/client-async/logic/Logic.cpp | 4 +-- src/client/logic/Logic.cpp | 5 +-- src/common/CMakeLists.txt | 2 +- src/common/config/PathConfig.cpp | 65 +++++++++++++++++++++++++++++++++++ src/common/config/PathConfig.h | 52 ++++++++++++++++++++++++++++ src/common/sockets/SocketPath.cpp | 32 ----------------- src/common/sockets/SocketPath.h | 37 -------------------- src/service/main/Cynara.cpp | 32 ++--------------- src/service/main/Cynara.h | 17 ++++----- src/service/sockets/SocketManager.cpp | 10 +++--- 11 files changed, 140 insertions(+), 120 deletions(-) create mode 100644 src/common/config/PathConfig.cpp create mode 100644 src/common/config/PathConfig.h delete mode 100644 src/common/sockets/SocketPath.cpp delete mode 100644 src/common/sockets/SocketPath.h diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 0deccb9..506ecbf 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include "Logic.h" @@ -47,7 +47,7 @@ namespace Cynara { Logic::Logic() { - m_socketClient = std::make_shared(SocketPath::admin, + m_socketClient = std::make_shared(PathConfig::SocketPath::admin, std::make_shared()); } diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 8babbed..921c2d6 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include "Logic.h" @@ -45,7 +45,7 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) : m_statusCallback(callback, userStatusData) { m_socketClient = std::make_shared( - SocketPath::client, std::make_shared()); + PathConfig::SocketPath::client, std::make_shared()); m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index 4886b78..e05a168 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include @@ -48,7 +48,8 @@ static ProtocolFrameSequenceNumber generateSequenceNumber(void) { } Logic::Logic() { - m_socket = std::make_shared(SocketPath::client, std::make_shared()); + m_socket = std::make_shared(PathConfig::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 6cd0005..61debfd 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,6 +26,7 @@ INCLUDE_DIRECTORIES( ) SET(COMMON_SOURCES + ${COMMON_PATH}/config/PathConfig.cpp ${COMMON_PATH}/containers/BinaryQueue.cpp ${COMMON_PATH}/log/log.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp @@ -49,7 +50,6 @@ 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/config/PathConfig.cpp b/src/common/config/PathConfig.cpp new file mode 100644 index 0000000..a5a603b --- /dev/null +++ b/src/common/config/PathConfig.cpp @@ -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/common/config/PathConfig.cpp + * @author Zofia Abramowska + * @version 1.0 + * @brief This file specifies PathConfig namespace containing values of default cynara paths + */ + +#include "PathConfig.h" + +namespace Cynara { +namespace PathConfig { + +//main paths +const std::string statePath( +#ifdef CYNARA_STATE_PATH + CYNARA_STATE_PATH +#else + "/var/lib/cynara/" +#endif + ); + +const std::string libraryPath( +#ifdef CYNARA_LIB_PATH + CYNARA_LIB_PATH +#else + "/usr/lib/cynara/" +#endif + ); + +const std::string clientPath("/run/cynara/"); + +namespace SocketPath { +const std::string client(clientPath + "cynara.socket"); +const std::string admin(clientPath + "cynara-admin.socket"); +} // namespace SocketPath + +namespace StoragePath { +const std::string dbDir(statePath + "db/"); +} // namespace StoragePath + +namespace PluginPath { +const std::string clientDir(libraryPath + "plugin/client/"); +const std::string serviceDir(libraryPath + "plugin/service/"); +} // namespace PluginPath + +} // namespace PathConfig +} // namespace Cynara + + + diff --git a/src/common/config/PathConfig.h b/src/common/config/PathConfig.h new file mode 100644 index 0000000..27b10c2 --- /dev/null +++ b/src/common/config/PathConfig.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/config/PathConfig.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file specifies PathConfig namespace containing default cynara paths + */ + +#ifndef SRC_COMMON_CONFIG_PATHCONFIG_H_ +#define SRC_COMMON_CONFIG_PATHCONFIG_H_ + +#include + +namespace Cynara { +namespace PathConfig { + +extern const std::string statePath; +extern const std::string libraryPath; +extern const std::string clientPath; + +namespace SocketPath { +extern const std::string client; +extern const std::string admin; +} // namespace SocketPath + +namespace StoragePath { +extern const std::string dbDir; +} // namespace StoragePath + +namespace PluginPath { +extern const std::string clientDir; +extern const std::string serviceDir; +} // namespace PluginPath + +} // namespace PathConfig +} // namespace Cynara + +#endif /* SRC_COMMON_CONFIG_PATHCONFIG_H_ */ diff --git a/src/common/sockets/SocketPath.cpp b/src/common/sockets/SocketPath.cpp deleted file mode 100644 index c64e2ff..0000000 --- a/src/common/sockets/SocketPath.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ -/** - * @file src/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 deleted file mode 100644 index cca867d..0000000 --- a/src/common/sockets/SocketPath.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ -/** - * @file src/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/main/Cynara.cpp b/src/service/main/Cynara.cpp index 1a0d45e..c0f77ef 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -45,38 +46,11 @@ Cynara::~Cynara() { finalize(); } -const std::string Cynara::storageDir(void) { - std::string dir("/var/lib/cynara/"); - -#ifdef CYNARA_STATE_PATH - dir = CYNARA_STATE_PATH; -#else - LOGW("Cynara compiled without CYNARA_STATE_PATH flag. Using default database directory."); -#endif - - dir += "db/"; - LOGI("Cynara database path <%s>", dir.c_str()); - 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_pluginManager = std::make_shared(PathConfig::PluginPath::serviceDir); m_socketManager = std::make_shared(); - m_storageBackend = std::make_shared(storageDir()); + m_storageBackend = std::make_shared(PathConfig::StoragePath::dbDir); m_storage = std::make_shared(*m_storageBackend); m_logic->bindPluginManager(m_pluginManager); diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h index e89eda3..2eb94dc 100644 --- a/src/service/main/Cynara.h +++ b/src/service/main/Cynara.h @@ -28,16 +28,6 @@ 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: Cynara(); ~Cynara(); @@ -45,6 +35,13 @@ public: void init(void); void run(void); void finalize(void); + +private: + LogicPtr m_logic; + PluginManagerPtr m_pluginManager; + SocketManagerPtr m_socketManager; + StoragePtr m_storage; + StorageBackendPtr m_storageBackend; }; } // namespace Cynara diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index c9e1692..3161dc7 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -37,10 +37,10 @@ #include #include +#include #include #include #include -#include #include #include
@@ -73,10 +73,10 @@ void SocketManager::init(void) { const mode_t clientSocketUMask(0); const mode_t adminSocketUMask(0077); - createDomainSocket(std::make_shared(), SocketPath::client, clientSocketUMask, - true); - createDomainSocket(std::make_shared(), SocketPath::admin, adminSocketUMask, - false); + createDomainSocket(std::make_shared(), PathConfig::SocketPath::client, + clientSocketUMask, true); + createDomainSocket(std::make_shared(), PathConfig::SocketPath::admin, + adminSocketUMask, false); createSignalSocket(std::make_shared()); LOGI("SocketManger init done"); } -- 2.7.4 From aae388640a4fa6b772db232e28d6e4fc5a65278c Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 16 Oct 2014 18:35:48 +0200 Subject: [PATCH 10/16] Fix dlopened objects management * Add destroy function type, so deletion is compatible with allocation * Remove extern "C" from plugin creation/destruction typedefs * Add proper comments, so expected names of creation/destruction function symbol are known to API user Change-Id: I019f5bf83afc94945c8efc62e99dd324c419cc33 --- src/include/cynara-plugin.h | 17 +++++++++++++---- src/service/plugin/PluginManager.cpp | 18 ++++++++++++++++-- src/service/plugin/PluginManager.h | 3 ++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h index 83956fe..a9d6da7 100644 --- a/src/include/cynara-plugin.h +++ b/src/include/cynara-plugin.h @@ -34,11 +34,20 @@ namespace Cynara { class ExternalPluginInterface; -extern "C" { -typedef ExternalPluginInterface *(*createPlugin)(void); -} +/** + * Type of function used for creating objects implementing ExternalPluginInterface. + * Inside plugin library function with create_t signature should have symbol + * named "create". + */ +typedef ExternalPluginInterface *(*create_t)(void); +/** + * Type of function used for destroying objects created with "create". + * Inside plugin library function with destroy_t signature should have symbol + * named "destroy". + */ +typedef void (*destroy_t)(ExternalPluginInterface *); -//These typedefs will be defined in external headers +// These typedefs will be defined in external headers typedef std::string PluginData; typedef std::string AgentType; typedef std::vector PolicyTypes; diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp index 3d21b49..c591805 100644 --- a/src/service/plugin/PluginManager.cpp +++ b/src/service/plugin/PluginManager.cpp @@ -53,6 +53,14 @@ PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) { loadPlugins(); } +PluginManager::~PluginManager(void) { + // We have to be sure, that external objects will be destroyed + // before handles to libraries are closed. + for (auto &plugin : m_plugins) { + plugin.second.reset(); + } +} + ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) { return m_plugins[pType]; } @@ -90,7 +98,7 @@ void PluginManager::openPlugin(const std::string &path) { //Flush any previous errors dlerror(); - createPlugin func = reinterpret_cast(dlsym(handle, "create")); + create_t creator = reinterpret_cast(dlsym(handle, "create")); char *error; if ((error = dlerror()) != NULL) { @@ -98,7 +106,13 @@ void PluginManager::openPlugin(const std::string &path) { return; } - ExternalPluginPtr pluginPtr(func()); + destroy_t destroyer = reinterpret_cast(dlsym(handle, "destroy")); + if ((error = dlerror()) != NULL) { + LOGE("Couldn't resolve symbol from lib <%s> : <%s>", path.c_str(), error); + return; + } + + ExternalPluginPtr pluginPtr(creator(), destroyer); if (!pluginPtr) { LOGE("Couldn't create plugin for <%s>", path.c_str()); diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h index 6338cad..1abc6e6 100644 --- a/src/service/plugin/PluginManager.h +++ b/src/service/plugin/PluginManager.h @@ -23,6 +23,7 @@ #ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ #define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ +#include #include #include #include @@ -37,7 +38,7 @@ class PluginManager { public: PluginManager(const std::string &pluginDir); ExternalPluginPtr getPlugin(PolicyType pType); - ~PluginManager() {} + ~PluginManager(); private: typedef std::unique_ptr> PluginLibPtr; -- 2.7.4 From faf0647ea68e1114a28128b96598cdd4635bfb0c Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 16 Oct 2014 16:53:14 +0200 Subject: [PATCH 11/16] Add base class for external plugins * Make ExternalPluginInterface a base class providing only pure virtual getSupportedPolicyTypes() and publish its header * Change ExternalPluginInterface definition to ServicePluginInterface class and make it inherit after ExternalPluginInterface and publish its header as cynara-client-plugin.h * Rename InterpreterInterface to ClientServiceInterface, make it inherit after ExternalPluginInterface Change-Id: Ia572e2adb8a4486705f89903b31433d70d733381 --- packaging/cynara.spec | 2 + src/client-async/logic/Logic.cpp | 5 +- src/client-common/CMakeLists.txt | 1 + src/client-common/cache/CacheInterface.h | 6 +-- src/client-common/cache/CapacityCache.cpp | 2 +- src/client-common/plugins/NaiveInterpreter.cpp | 30 +++++++++++ src/client-common/plugins/NaiveInterpreter.h | 9 +++- src/client-common/plugins/PluginInterface.h | 48 ----------------- src/client/logic/Logic.cpp | 6 +-- src/common/CMakeLists.txt | 4 ++ src/common/plugin/ExternalPluginInterface.h | 60 +++++++++++++++++++++ src/include/CMakeLists.txt | 1 + src/include/cynara-client-plugin.h | 74 ++++++++++++++++++++++++++ src/include/cynara-plugin.h | 38 +++++-------- src/service/logic/Logic.cpp | 22 +++++--- src/service/plugin/PluginManager.cpp | 2 +- src/service/plugin/PluginManager.h | 2 +- 17 files changed, 220 insertions(+), 92 deletions(-) create mode 100644 src/client-common/plugins/NaiveInterpreter.cpp delete mode 100644 src/client-common/plugins/PluginInterface.h create mode 100644 src/common/plugin/ExternalPluginInterface.h create mode 100644 src/include/cynara-client-plugin.h diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 68d52ce..743f2a7 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -482,12 +482,14 @@ fi %files -n libcynara-commons-devel %{_includedir}/cynara/cynara-policy-types.h +%{_includedir}/cynara/plugin/ExternalPluginInterface.h %{_includedir}/cynara/types/PolicyResult.h %{_includedir}/cynara/types/PolicyType.h %{_libdir}/libcynara-commons.so %files -n libcynara-plugin-devel %{_includedir}/cynara/cynara-plugin.h +%{_includedir}/cynara/cynara-client-plugin.h %{_libdir}/pkgconfig/cynara-plugin.pc %files -n cynara-tests diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 921c2d6..bfb494c 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -49,8 +49,9 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter); + for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { + m_cache->registerPlugin(type, naiveInterpreter); + } } Logic::~Logic() { diff --git a/src/client-common/CMakeLists.txt b/src/client-common/CMakeLists.txt index 90e09d7..5436884 100644 --- a/src/client-common/CMakeLists.txt +++ b/src/client-common/CMakeLists.txt @@ -28,6 +28,7 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_COMMON_SOURCES ${LIB_CYNARA_COMMON_PATH}/cache/CapacityCache.cpp + ${LIB_CYNARA_COMMON_PATH}/plugins/NaiveInterpreter.cpp ) ADD_DEFINITIONS("-fvisibility=default") diff --git a/src/client-common/cache/CacheInterface.h b/src/client-common/cache/CacheInterface.h index 57455b8..03b7624 100644 --- a/src/client-common/cache/CacheInterface.h +++ b/src/client-common/cache/CacheInterface.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ public: const PolicyKey &key, const PolicyResult &result) = 0; - void registerPlugin(const PolicyType policyType, InterpreterInterfacePtr plugin) { + void registerPlugin(const PolicyType policyType, ClientPluginInterfacePtr plugin) { m_plugins[policyType] = plugin; } @@ -59,7 +59,7 @@ public: virtual ~PluginCache() {}; protected: - std::map m_plugins; + std::map m_plugins; }; } // namespace Cynara diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index d07bb2c..7eb7e34 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -55,7 +55,7 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { } //Is it still usable? - InterpreterInterfacePtr plugin = pluginIt->second; + ClientPluginInterfacePtr plugin = pluginIt->second; auto &prevSession = std::get<1>(cachedValue); auto usageIt = std::get<2>(cachedValue); bool updateSession = false; diff --git a/src/client-common/plugins/NaiveInterpreter.cpp b/src/client-common/plugins/NaiveInterpreter.cpp new file mode 100644 index 0000000..7141cb7 --- /dev/null +++ b/src/client-common/plugins/NaiveInterpreter.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/client-common/plugins/NaiveInterpreter.cpp + * @author Zofia Abramowska + * @version 1.0 + * @brief This file contains NaiveInterpreter supported types definition. + */ + +#include + +namespace Cynara { + + const std::vector NaiveInterpreter::s_supportedTypes = + {PredefinedPolicyType::ALLOW, PredefinedPolicyType::DENY}; + +} diff --git a/src/client-common/plugins/NaiveInterpreter.h b/src/client-common/plugins/NaiveInterpreter.h index e9e8ba4..8099362 100644 --- a/src/client-common/plugins/NaiveInterpreter.h +++ b/src/client-common/plugins/NaiveInterpreter.h @@ -28,7 +28,8 @@ namespace Cynara { -class NaiveInterpreter : public InterpreterInterface { +class NaiveInterpreter : public ClientPluginInterface { +public: bool isUsable(const ClientSession &session UNUSED, const ClientSession &prevSession UNUSED, bool &updateSession UNUSED, PolicyResult &result UNUSED) { return true; @@ -43,6 +44,12 @@ class NaiveInterpreter : public InterpreterInterface { else return CYNARA_API_ACCESS_DENIED; } + + const std::vector &getSupportedPolicyTypes(void) { + return s_supportedTypes; + } +private: + static const std::vector s_supportedTypes; }; } // namespace Cynara diff --git a/src/client-common/plugins/PluginInterface.h b/src/client-common/plugins/PluginInterface.h deleted file mode 100644 index 54bd341..0000000 --- a/src/client-common/plugins/PluginInterface.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ -/** - * @file src/client-common/plugins/PluginInterface.h - * @author Zofia Abramowska - * @version 1.0 - * @brief This file contains plugin interface definitions. - */ - -#ifndef SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ -#define SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ - -#include - -#include -#include - -namespace Cynara { - -class InterpreterInterface; -typedef std::shared_ptr InterpreterInterfacePtr; - -class InterpreterInterface { -public: - virtual bool isCacheable(const ClientSession &session, const PolicyResult &result) = 0; - virtual bool isUsable(const ClientSession &session, const ClientSession &prevSession, - bool &updateSession, PolicyResult &result) = 0; - virtual int toResult(const ClientSession &session, PolicyResult &result) = 0; - - virtual ~InterpreterInterface() {}; -}; - -} // namespace Cynara - -#endif // SRC_CLIENT_COMMON_PLUGINS_PLUGININTERFACE_H_ diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index e05a168..498e53c 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -52,9 +52,9 @@ Logic::Logic() { std::make_shared()); m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter); - m_cache->registerPlugin(PredefinedPolicyType::BUCKET, naiveInterpreter); + for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { + m_cache->registerPlugin(type, naiveInterpreter); + } } int Logic::check(const std::string &client, const ClientSession &session, const std::string &user, diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 61debfd..9dc48de 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -91,3 +91,7 @@ INSTALL(FILES ${COMMON_PATH}/types/PolicyType.h DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/types ) +INSTALL(FILES + ${COMMON_PATH}/plugin/ExternalPluginInterface.h + DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/plugin + ) diff --git a/src/common/plugin/ExternalPluginInterface.h b/src/common/plugin/ExternalPluginInterface.h new file mode 100644 index 0000000..bf3c7fe --- /dev/null +++ b/src/common/plugin/ExternalPluginInterface.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/plugin/ExternalPluginInterface.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines cynara side external plugin interface + */ + +#ifndef SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ +#define SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ + +#include + +#include + +namespace Cynara { + +class ExternalPluginInterface; + +/** + * Type of function used for creating objects implementing ExternalPluginInterface. + * Inside plugin library function with create_t signature should have symbol + * named "create". + */ +typedef ExternalPluginInterface *(*create_t)(void); + +/** + * Type of function used for destroying objects created with "create". + * Inside plugin library function with destroy_t signature should have symbol + * named "destroy". + */ +typedef void (*destroy_t)(ExternalPluginInterface *); + +class ExternalPluginInterface { +public: + + /** + * Policy type supported by plugin. + */ + virtual const std::vector &getSupportedPolicyTypes(void) = 0; + virtual ~ExternalPluginInterface() {} +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_PLUGIN_EXTERNALPLUGININTERFACE_H_ */ diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index 1d672a8..b43bd1f 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin-types.h ${CYNARA_PATH}/include/cynara-client.h ${CYNARA_PATH}/include/cynara-client-async.h + ${CYNARA_PATH}/include/cynara-client-plugin.h ${CYNARA_PATH}/include/cynara-creds-commons.h ${CYNARA_PATH}/include/cynara-creds-dbus.h ${CYNARA_PATH}/include/cynara-creds-socket.h diff --git a/src/include/cynara-client-plugin.h b/src/include/cynara-client-plugin.h new file mode 100644 index 0000000..3d39ad7 --- /dev/null +++ b/src/include/cynara-client-plugin.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/include/cynara-client-plugin.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines cynara client side of external plugin interface - + * ClientPluginInterface. + */ + +#ifndef CYNARACLIENTPLUGIN_H_ +#define CYNARACLIENTPLUGIN_H_ + +#include + +#include +#include +#include + +namespace Cynara { + +class ClientPluginInterface; +typedef std::shared_ptr ClientPluginInterfacePtr; + +/** + * A class defining external plugins interface. + * These plugins work inside of cynara client library. They interpret + * PolicyResult returned by cynara in terms of: + * a) cacheability - tells, whether value should be cached (for e.g. policyType like + * ALLOW_ONCE should not be cached) + * b) usability - whether cache entry can still be used (for e.g. policy allowing access for + * given type) + * c) value - translates PolicyResult to CYNARA_API_ACCESS_ALLOWED or CYNARA_API_ACCESS_DENIED + * + * Plugin implementing ClientPluginInterface must implement ExternalPluginInterface. + * Creation/destruction functions with signatures compatible to Cynara::create_t and + * Cynara::destroy_t must be provided as factories of ClientPluginInterface. + */ +class ClientPluginInterface : public ExternalPluginInterface { +public: + + /** + * Return entry cacheability + */ + virtual bool isCacheable(const ClientSession &session, const PolicyResult &result) = 0; + /** + * Return entry cacheability + */ + virtual bool isUsable(const ClientSession &session, const ClientSession &prevSession, + bool &updateSession, PolicyResult &result) = 0; + /** + * Translate PolicyResult to CYNARA_API_ACCESS_ALLOWED or CYNARA_API_ACCESS_DENIED + */ + virtual int toResult(const ClientSession &session, PolicyResult &result) = 0; + + virtual ~ClientPluginInterface() {}; +}; + +} + +#endif // CYNARACLIENTPLUGIN_H_ diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h index a9d6da7..20e5e5c 100644 --- a/src/include/cynara-plugin.h +++ b/src/include/cynara-plugin.h @@ -17,7 +17,8 @@ * @file src/include/cynara-plugin.h * @author Zofia Abramowska * @version 1.0 - * @brief This file defines cynara side external plugin interface + * @brief This file defines cynara service side of external plugin interface - + * ServicePluginInterface */ #ifndef CYNARA_PLUGIN_H_ @@ -27,30 +28,18 @@ #include #include +#include #include #include namespace Cynara { -class ExternalPluginInterface; - -/** - * Type of function used for creating objects implementing ExternalPluginInterface. - * Inside plugin library function with create_t signature should have symbol - * named "create". - */ -typedef ExternalPluginInterface *(*create_t)(void); -/** - * Type of function used for destroying objects created with "create". - * Inside plugin library function with destroy_t signature should have symbol - * named "destroy". - */ -typedef void (*destroy_t)(ExternalPluginInterface *); - -// These typedefs will be defined in external headers +//These typedefs will be defined in external headers typedef std::string PluginData; typedef std::string AgentType; -typedef std::vector PolicyTypes; + +class ServicePluginInterface; +typedef std::shared_ptr ServicePluginInterfacePtr; /** * A class defining external plugins interface. @@ -58,9 +47,13 @@ typedef std::vector PolicyTypes; * response through check instantly or require communication * with given type of agent. Agent must be registered through * cynara-agent API. + * + * Plugin implementing ServicePluginInterface must implement ExternalPluginInterface. + * Creation/destruction functions with signatures compatible to Cynara::create_t and + * Cynara::destroy_t must be provided as factories of ServicePluginInterface. */ -class ExternalPluginInterface { +class ServicePluginInterface : public ExternalPluginInterface { public: /** * Enum indicating status of calling plugin method. @@ -74,11 +67,6 @@ public: }; /** - * Policy type supported by plugin. - */ - virtual PolicyTypes getSupportedPolicyTypes(void) = 0; - - /** * Asks plugin, what kind of permission does client, user and privilege has. * * @param[in] client @@ -107,7 +95,7 @@ public: const std::string &privilege, const PluginData &agentData, PolicyResult &result) noexcept = 0; - virtual ~ExternalPluginInterface() {}; + virtual ~ServicePluginInterface() {}; }; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index ca56d64..d4cc634 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -20,6 +20,8 @@ * @brief This file implements main class of logic layer in cynara service */ +#include + #include #include #include @@ -29,8 +31,9 @@ #include #include #include +#include -#include +#include #include
#include @@ -44,9 +47,8 @@ #include #include #include -#include - #include +#include #include "Logic.h" @@ -107,16 +109,22 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, throw PluginNotFoundException(result); } + ServicePluginInterfacePtr servicePlugin = + std::dynamic_pointer_cast(plugin); + if (!plugin) { + throw PluginNotFoundException(result); + } + AgentType requiredAgent; PluginData pluginData; - auto ret = plugin->check(key.client().toString(), key.user().toString(), - key.privilege().toString(), result, requiredAgent, pluginData); + auto ret = servicePlugin->check(key.client().toString(), key.user().toString(), + key.privilege().toString(), result, requiredAgent, pluginData); switch (ret) { - case ExternalPluginInterface::PluginStatus::ANSWER_READY: + case ServicePluginInterface::PluginStatus::ANSWER_READY: return true; - case ExternalPluginInterface::PluginStatus::ANSWER_NOTREADY: + case ServicePluginInterface::PluginStatus::ANSWER_NOTREADY: //todo send request to agent //context should be saved in plugin in order to return answer when ready return false; diff --git a/src/service/plugin/PluginManager.cpp b/src/service/plugin/PluginManager.cpp index c591805..8062683 100644 --- a/src/service/plugin/PluginManager.cpp +++ b/src/service/plugin/PluginManager.cpp @@ -119,7 +119,7 @@ void PluginManager::openPlugin(const std::string &path) { return; } - PolicyTypes policies = pluginPtr->getSupportedPolicyTypes(); + auto policies = pluginPtr->getSupportedPolicyTypes(); if (policies.empty()) { LOGE("Plugin <%s> does not support any type!", path.c_str()); return; diff --git a/src/service/plugin/PluginManager.h b/src/service/plugin/PluginManager.h index 1abc6e6..c2372e6 100644 --- a/src/service/plugin/PluginManager.h +++ b/src/service/plugin/PluginManager.h @@ -29,7 +29,7 @@ #include #include -#include +#include namespace Cynara { typedef std::shared_ptr ExternalPluginPtr; -- 2.7.4 From 0be98a2867acbe4e0e52c5b3211a5fd6ff071ab5 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 17 Oct 2014 18:28:34 +0200 Subject: [PATCH 12/16] Add PluginManager to CapacityCache Change-Id: Icdaf1df3793db0a43ae4aadcf2d8d306b04f650f --- src/client-common/cache/CapacityCache.cpp | 17 ++++++++++++----- src/client-common/cache/CapacityCache.h | 6 +++++- src/common/CMakeLists.txt | 1 + src/{service => common}/plugin/PluginManager.cpp | 0 src/{service => common}/plugin/PluginManager.h | 0 src/service/CMakeLists.txt | 1 - 6 files changed, 18 insertions(+), 7 deletions(-) rename src/{service => common}/plugin/PluginManager.cpp (100%) rename src/{service => common}/plugin/PluginManager.h (100%) diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index 7eb7e34..3174744 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -47,15 +47,22 @@ int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { auto &cachedValue = resultIt->second; auto &policyResult = std::get<0>(cachedValue); + ClientPluginInterfacePtr plugin; auto pluginIt = m_plugins.find(policyResult.policyType()); - if (pluginIt == m_plugins.end()) { - LOGE("No plugin registered for given PolicyType : %" PRIu16, - policyResult.policyType()); - return CYNARA_API_ACCESS_DENIED; + if (pluginIt != m_plugins.end()) { + plugin = pluginIt->second; + } else { + plugin = std::dynamic_pointer_cast( + m_pluginManager.getPlugin(policyResult.policyType())); + if (!plugin) { + LOGE("No plugin registered for given PolicyType : %" PRIu16, + policyResult.policyType()); + return CYNARA_API_ACCESS_DENIED; + } } //Is it still usable? - ClientPluginInterfacePtr plugin = pluginIt->second; + auto &prevSession = std::get<1>(cachedValue); auto usageIt = std::get<2>(cachedValue); bool updateSession = false; diff --git a/src/client-common/cache/CapacityCache.h b/src/client-common/cache/CapacityCache.h index 4218078..24e1092 100644 --- a/src/client-common/cache/CapacityCache.h +++ b/src/client-common/cache/CapacityCache.h @@ -29,6 +29,9 @@ #include +#include +#include + namespace Cynara { class CapacityCache : public PluginCache { @@ -36,7 +39,7 @@ public: static const std::size_t CACHE_DEFAULT_CAPACITY = 10000; CapacityCache(std::size_t capacity = CACHE_DEFAULT_CAPACITY) : - m_capacity(capacity) {} + m_capacity(capacity), m_pluginManager(PathConfig::PluginPath::clientDir) {} int get(const ClientSession &session, const PolicyKey &key); int update(const ClientSession& session, @@ -57,6 +60,7 @@ private: KeyUsageList m_keyUsage; KeyValueMap m_keyValue; + PluginManager m_pluginManager; }; } //namespace Cynara diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9dc48de..98f5133 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -29,6 +29,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/config/PathConfig.cpp ${COMMON_PATH}/containers/BinaryQueue.cpp ${COMMON_PATH}/log/log.cpp + ${COMMON_PATH}/plugin/PluginManager.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp ${COMMON_PATH}/protocol/ProtocolClient.cpp ${COMMON_PATH}/protocol/ProtocolFrame.cpp diff --git a/src/service/plugin/PluginManager.cpp b/src/common/plugin/PluginManager.cpp similarity index 100% rename from src/service/plugin/PluginManager.cpp rename to src/common/plugin/PluginManager.cpp diff --git a/src/service/plugin/PluginManager.h b/src/common/plugin/PluginManager.h similarity index 100% rename from src/service/plugin/PluginManager.h rename to src/common/plugin/PluginManager.h diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index f8d2eb8..c317d8e 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -22,7 +22,6 @@ SET(CYNARA_SOURCES ${CYNARA_SERVICE_PATH}/logic/Logic.cpp ${CYNARA_SERVICE_PATH}/main/Cynara.cpp ${CYNARA_SERVICE_PATH}/main/main.cpp - ${CYNARA_SERVICE_PATH}/plugin/PluginManager.cpp ${CYNARA_SERVICE_PATH}/sockets/Descriptor.cpp ${CYNARA_SERVICE_PATH}/sockets/SocketManager.cpp ) -- 2.7.4 From 73bee30c040050883a812bdbf2e02ad4cd54f776 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Mon, 15 Sep 2014 14:47:22 +0200 Subject: [PATCH 13/16] Add agent socket & dummy agent protocol This change introduces new systemd based socket and protocol for communication with agents. Protocol does not contain any agent specific frame information for now. Change-Id: I83e2211a25fd93792a46a64c1df519efb1cedfed --- packaging/cynara.spec | 3 ++ src/common/CMakeLists.txt | 1 + src/common/common.h | 1 - src/common/config/PathConfig.cpp | 1 + src/common/config/PathConfig.h | 1 + src/common/protocol/ProtocolAgent.cpp | 84 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAgent.h | 47 ++++++++++++++++++++ src/service/sockets/SocketManager.cpp | 4 ++ systemd/CMakeLists.txt | 1 + systemd/cynara-agent.socket | 14 ++++++ systemd/cynara.service | 1 + 11 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/common/protocol/ProtocolAgent.cpp create mode 100644 src/common/protocol/ProtocolAgent.h create mode 100644 systemd/cynara-agent.socket diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 743f2a7..8a3e298 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -287,6 +287,7 @@ mkdir -p %{buildroot}/%{tests_dir}/empty_db cp -a db* %{buildroot}/%{tests_dir} ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket +ln -s ../cynara-agent.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-agent.socket %pre id -g %{group_name} > /dev/null 2>&1 @@ -425,6 +426,8 @@ fi %attr(-,root,root) /usr/lib/systemd/system/cynara.socket %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket %attr(-,root,root) /usr/lib/systemd/system/cynara-admin.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/cynara-agent.socket +%attr(-,root,root) /usr/lib/systemd/system/cynara-agent.socket %dir %attr(700,cynara,cynara) %{state_path} %files -n libcynara-client diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 98f5133..72b7d7f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -31,6 +31,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/log/log.cpp ${COMMON_PATH}/plugin/PluginManager.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp + ${COMMON_PATH}/protocol/ProtocolAgent.cpp ${COMMON_PATH}/protocol/ProtocolClient.cpp ${COMMON_PATH}/protocol/ProtocolFrame.cpp ${COMMON_PATH}/protocol/ProtocolFrameHeader.cpp diff --git a/src/common/common.h b/src/common/common.h index 5d93cdc..95ff89c 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -32,5 +32,4 @@ #include "types/PolicyTypeExtension.h" - #endif /* COMMON_H */ diff --git a/src/common/config/PathConfig.cpp b/src/common/config/PathConfig.cpp index a5a603b..f2799a1 100644 --- a/src/common/config/PathConfig.cpp +++ b/src/common/config/PathConfig.cpp @@ -47,6 +47,7 @@ const std::string clientPath("/run/cynara/"); namespace SocketPath { const std::string client(clientPath + "cynara.socket"); const std::string admin(clientPath + "cynara-admin.socket"); +const std::string agent(clientPath + "cynara-agent.socket"); } // namespace SocketPath namespace StoragePath { diff --git a/src/common/config/PathConfig.h b/src/common/config/PathConfig.h index 27b10c2..2f5836a 100644 --- a/src/common/config/PathConfig.h +++ b/src/common/config/PathConfig.h @@ -35,6 +35,7 @@ extern const std::string clientPath; namespace SocketPath { extern const std::string client; extern const std::string admin; +extern const std::string agent; } // namespace SocketPath namespace StoragePath { diff --git a/src/common/protocol/ProtocolAgent.cpp b/src/common/protocol/ProtocolAgent.cpp new file mode 100644 index 0000000..f4d26a1 --- /dev/null +++ b/src/common/protocol/ProtocolAgent.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/protocol/ProtocolAgent.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements protocol class for communication with agent + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ProtocolAgent.h" + +namespace Cynara { + +ProtocolAgent::ProtocolAgent() { +} + +ProtocolAgent::~ProtocolAgent() { +} + +ProtocolPtr ProtocolAgent::clone(void) { + return std::make_shared(); +} + +RequestPtr ProtocolAgent::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); + switch (opCode) { + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +ResponsePtr ProtocolAgent::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); + switch (opCode) { + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +} // namespace Cynara diff --git a/src/common/protocol/ProtocolAgent.h b/src/common/protocol/ProtocolAgent.h new file mode 100644 index 0000000..68baf46 --- /dev/null +++ b/src/common/protocol/ProtocolAgent.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/protocol/ProtocolAgent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines protocol class for communication with agent + */ + +#ifndef SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ +#define SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ + +#include +#include +#include + +#include "Protocol.h" + +namespace Cynara { + +class ProtocolAgent : public Protocol { +public: + ProtocolAgent(); + virtual ~ProtocolAgent(); + + virtual ProtocolPtr clone(void); + + virtual RequestPtr extractRequestFromBuffer(BinaryQueuePtr bufferQueue); + virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_PROTOCOL_PROTOCOLAGENT_H_ */ diff --git a/src/service/sockets/SocketManager.cpp b/src/service/sockets/SocketManager.cpp index 3161dc7..e454271 100644 --- a/src/service/sockets/SocketManager.cpp +++ b/src/service/sockets/SocketManager.cpp @@ -45,6 +45,7 @@ #include #include
#include +#include #include #include #include @@ -72,11 +73,14 @@ void SocketManager::init(void) { LOGI("SocketManger init start"); const mode_t clientSocketUMask(0); const mode_t adminSocketUMask(0077); + const mode_t agentSocketUMask(0); createDomainSocket(std::make_shared(), PathConfig::SocketPath::client, clientSocketUMask, true); createDomainSocket(std::make_shared(), PathConfig::SocketPath::admin, adminSocketUMask, false); + createDomainSocket(std::make_shared(), PathConfig::SocketPath::agent, + agentSocketUMask, false); createSignalSocket(std::make_shared()); LOGI("SocketManger init done"); } diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index 8fc27e7..a540263 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/cynara.target ${CMAKE_SOURCE_DIR}/systemd/cynara.socket ${CMAKE_SOURCE_DIR}/systemd/cynara-admin.socket + ${CMAKE_SOURCE_DIR}/systemd/cynara-agent.socket DESTINATION lib/systemd/system ) diff --git a/systemd/cynara-agent.socket b/systemd/cynara-agent.socket new file mode 100644 index 0000000..96fc54a --- /dev/null +++ b/systemd/cynara-agent.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/cynara/cynara-agent.socket +SocketMode=0060 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=cynara.service + +[Unit] +Wants=cynara.target +Before=cynara.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/cynara.service b/systemd/cynara.service index 847a294..99176fa 100644 --- a/systemd/cynara.service +++ b/systemd/cynara.service @@ -12,6 +12,7 @@ Restart=always Sockets=cynara.socket Sockets=cynara-admin.socket +Sockets=cynara-agent.socket UMask=0000 User=cynara -- 2.7.4 From 03998323f9b30dd11cd920bbc0531029dbf0c063 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 23 Sep 2014 13:52:19 +0200 Subject: [PATCH 14/16] Add agent API This patch introduces API for agents cooperating with plugins. Agents communicate with plugins via cynara service. Change-Id: I0f6233838f27370ee980655ad09be9fd10ae1bce --- src/include/cynara-agent.h | 213 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/include/cynara-agent.h diff --git a/src/include/cynara-agent.h b/src/include/cynara-agent.h new file mode 100644 index 0000000..43026cb --- /dev/null +++ b/src/include/cynara-agent.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/include/cynara-agent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains agent APIs available with libcynara-agent. + */ + +#ifndef CYNARA_AGENT_H +#define CYNARA_AGENT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint16_t cynara_agent_req_id; +typedef struct cynara_agent cynara_agent; + +/** + * \enum cynara_agent_msg_type + * Values specifying type of message. + * + * \var cynara_agent_msg_type::CYNARA_MSG_TYPE_ACTION + * Message of this type indicates its content is a request for performing an action or response to + * such request. + * + * \var cynara_agent_msg_type::CYNARA_MSG_TYPE_CANCEL + * Message of this type indicates its content is a request for canceling action or response to such + * request. + */ +typedef enum { + CYNARA_MSG_TYPE_ACTION, + CYNARA_MSG_TYPE_CANCEL +} cynara_agent_msg_type; + +/** + * \par Description: + * Initialize cynara-agent library. + * Create structure used in following API calls. + * + * \par Purpose: + * This API must be used prior to calling other agent API functions. + * + * \par Typical use case: + * Once before other agent API functions are called. + * + * \par Method of function operation: + * This API initializes inner library structures and in case of success returns cynara_agent + * structure. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Structure cynara_agent created by this function should be released with cynara_agent_finish. + * + * \param[out] pp_cynara_agent Place holder for created cynara_agent structure. + * \param[in] p_agent_type Type (name) of agent used by cynara for communication agent<->plugin. + * + * \return CYNARA_API_SUCCESS on success, or error code on error. + */ +int cynara_agent_initialize(cynara_agent **pp_cynara_agent, const char *p_agent_type); + +/** + * \par Description: + * Release cynara-agent library and destroy structure created with cynara_agent_initialize(). + * + * \par Purpose: + * This API should be used to clean up after usage of cynara-agent library. + * + * \par Typical use case: + * Once after connection to cynara is not needed. + * + * \par Method of function operation: + * This API releases inner library structure and destroys cynara_agent structure. Connection to + * cynara service is closed. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread-safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * No other call to cynara-agent library should be made after call to cynara_agent_finish() except + * cynara_agent_initialize(). + * + * \param[in] p_cynara_agent cynara_agent structure. If NULL, then the call has no effect. + */ +int cynara_agent_finish(cynara_agent *p_cynara_agent); + +/** + * \par Description: + * Get request from cynara service. + * + * \par Purpose: + * This API should be used to get request from cynara service. Request is generated by corresponding + * plugin loaded into cynara service. + * + * \par Typical use case: + * Agent waits for request from cynara service. Request may be either ask for performing agent + * specific action or ask for canceling such action. Agent calls this function when is ready to + * perform or cancel an action. + * + * \par Method of function operation: + * Function reads data incoming from cynara service and if at least one complete request is ready + * then returns with CYNARA_API_SUCCESS code. Request type, request id and specific + * plugin data are stored in given arguments. Function returns exactly one request. If there are + * more then one requests ready to get then one must call this function multiple times. + * This function is blocking which means that if there is no request from cynara service it will not + * return. On success, buffer for plugin specific data is allocated and size is set. Developer is + * responsible for freeing this memory using free() function. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Call to cynara_agent_get_request() needs cynara_agent structure to be created first. + * Use cynara_agent_initialize() before calling this function. + * After CYNARA_API_ACCESS_DENIED error is returned agent should be terminated or at least should + * not invoke neither cynara_agent_get_request() nor cynara_agent_put_response() functions. + * + * \param[in] p_cynara_agent cynara_agent structure. + * \param[out] req_type Request type, demand an action or cancel this action. + * \param[out] req_id Request identifier used to pair with answer #cynara_agent_put_response() and + * cancel request. + * \param[out] data Plugin specific data. Buffer is allocated in this function and developer is + * responsible for freeing it using free() function. Buffer is filled with data + * from corresponding plugin. If there is no enough memory for data + * CYNARA_API_OUT_OF_MEMORY is returned and all arguments remain untouched. + * \param[out] data_size Size of plugin data (bytes count). In case of out of memory this value + * stays untouched. + * + * \return CYNARA_API_SUCCESS on successfully read request, or negative error code otherwise. + */ +int cynara_agent_get_request(cynara_agent *p_cynara_agent, cynara_agent_msg_type *req_type, + cynara_agent_req_id *req_id, void **data, size_t *data_size); + +/** + * \par Description: + * Send response to cynara service. + * + * \par Purpose: + * This API should be used to send response to cynara service. + * + * \par Typical use case: + * Agent calls this function when is ready to answer request for action or cancel request. + * + * \par Method of function operation: + * Function sends data to cynara service. Data contains answer for previously got question. + * Answer may be of type CYNARA_MSG_TYPE_ACTION or CYNARA_MSG_TYPE_CANCEL. Type is + * CYNARA_MSG_TYPE_ACTION when request for an action was processed and answer is ready, or + * CYNARA_MSG_TYPE_CANCEL when processing request for an action was interrupted by cancel request. + * Agent must send exactly one response per one request and cancel. If request is processed before + * cancel message arrives the agent sends action response. If cancel arrives before action request + * is processed then agent sends cancel response and drops processing related action. + * Request id in response must be the same as request id in corresponding request. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Thread safety: + * This function is NOT thread safe. If functions from described API are called by multithreaded + * application from different threads, they must be put into protected critical section. + * + * \par Important notes: + * Call to cynara_agent_get_request() needs cynara_agent structure to be created first. + * Use cynara_agent_initialize() before calling this function. Also successful call to + * cynara_agent_get_request() is needed before calling this function. + * + * \param[in] p_cynara_agent cynara_agent structure. + * \param[in] resp_type Response type - see Method of operation for details. + * \param[in] req_id Request identifier obtained from request. + * \param[in] data Plugin specific data. If necessary agent should fill this buffer with data + * directed to plugin. + * \param[in] data_size Size of plugin data (bytes count). + * + * \return CYNARA_API_SUCCESS on successfully read request, or negative error code otherwise. + */ +int cynara_agent_put_response(cynara_agent *p_cynara_agent, const cynara_agent_msg_type resp_type, + const cynara_agent_req_id req_id, const void *data, + const size_t data_size); + +#ifdef __cplusplus +} +#endif + +#endif /* CYNARA_AGENT_H */ -- 2.7.4 From f242b4ad2e55d02d869e0a7b7cff508796ac4119 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 2 Oct 2014 14:06:45 +0200 Subject: [PATCH 15/16] Add agent library stub implementation This patch introduces implementation of agent library. Connection to cynara service is not yet implemented. Only basic structure of library is created. Change-Id: Iff771cbff35c1eb4f0c3842631f2fd65ea322ee8 --- CMakeLists.txt | 1 + packaging/cynara.spec | 57 ++++++++++--- packaging/libcynara-agent.manifest | 5 ++ pkgconfig/CMakeLists.txt | 1 + pkgconfig/cynara-agent/CMakeLists.txt | 25 ++++++ pkgconfig/cynara-agent/cynara-agent.pc.in | 11 +++ src/CMakeLists.txt | 1 + src/agent/CMakeLists.txt | 47 +++++++++++ src/agent/api/ApiInterface.h | 47 +++++++++++ src/agent/api/agent-api.cpp | 125 ++++++++++++++++++++++++++++ src/agent/logic/Logic.cpp | 47 +++++++++++ src/agent/logic/Logic.h | 49 +++++++++++ src/common/CMakeLists.txt | 1 + src/common/request/pointers.h | 3 + src/common/response/AgentActionResponse.cpp | 36 ++++++++ src/common/response/AgentActionResponse.h | 59 +++++++++++++ src/common/response/ResponseTaker.cpp | 4 + src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 + src/common/types/Agent.h | 37 ++++++++ src/include/CMakeLists.txt | 1 + 21 files changed, 550 insertions(+), 11 deletions(-) create mode 100644 packaging/libcynara-agent.manifest create mode 100644 pkgconfig/cynara-agent/CMakeLists.txt create mode 100644 pkgconfig/cynara-agent/cynara-agent.pc.in create mode 100644 src/agent/CMakeLists.txt create mode 100644 src/agent/api/ApiInterface.h create mode 100644 src/agent/api/agent-api.cpp create mode 100644 src/agent/logic/Logic.cpp create mode 100644 src/agent/logic/Logic.h create mode 100644 src/common/response/AgentActionResponse.cpp create mode 100644 src/common/response/AgentActionResponse.h create mode 100644 src/common/types/Agent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c72d22..dc951bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ SET(TARGET_LIB_CYNARA "cynara-client") SET(TARGET_LIB_CYNARA_ASYNC "cynara-client-async") SET(TARGET_LIB_CYNARA_COMMON "cynara-client-commons") SET(TARGET_LIB_CYNARA_ADMIN "cynara-admin") +SET(TARGET_LIB_CYNARA_AGENT "cynara-agent") SET(TARGET_CYNARA_COMMON "cynara-commons") SET(TARGET_CYNARA_TESTS "cynara-tests") SET(TARGET_LIB_CREDS_COMMONS "cynara-creds-commons") diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 8a3e298..88e9209 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -11,14 +11,15 @@ Source1002: libcynara-client.manifest Source1003: libcynara-client-async.manifest Source1004: libcynara-admin.manifest Source1005: cynara-tests.manifest -Source1006: libcynara-client-commons.manifest -Source1007: libcynara-commons.manifest -Source1008: libcynara-creds-commons.manifest -Source1009: libcynara-creds-dbus.manifest -Source1010: libcynara-creds-socket.manifest -Source1011: libcynara-session.manifest -Source1012: libcynara-storage.manifest -Source1013: cynara-db-migration.manifest +Source1006: libcynara-agent.manifest +Source1007: libcynara-client-commons.manifest +Source1008: libcynara-commons.manifest +Source1009: libcynara-creds-commons.manifest +Source1010: libcynara-creds-dbus.manifest +Source1011: libcynara-creds-socket.manifest +Source1012: libcynara-session.manifest +Source1013: libcynara-storage.manifest +Source1014: cynara-db-migration.manifest Requires: default-ac-domains Requires(pre): pwdutils Requires(pre): cynara-db-migration >= %{version}-%{release} @@ -51,9 +52,8 @@ BuildRequires: pkgconfig(libunwind) %description service, client libraries (libcynara-client, libcynara-client-async, libcynara-admin), -helper libraries (libcynara-session, libcynara-creds-common, libcynara-creds-dbus, -libcynara-creds-socket) -and tests (cynara-tests) +agent library, helper libraries (libcynara-session, libcynara-creds-common, libcynara-creds-dbus, +libcynara-creds-socket) and tests (cynara-tests) ####################################################### %package -n libcynara-client @@ -118,6 +118,22 @@ Requires: libcynara-commons-devel = %{version}-%{release} admin client library (devel) for setting, listing and removing policies ####################################################### +%package -n libcynara-agent +Summary: Cynara - agent client library +Requires: cynara = %{version}-%{release} + +%description -n libcynara-agent +agent client library for communication with cynara service and plugins + +%package -n libcynara-agent-devel +Summary: Cynara - agent client library (devel) +Requires: libcynara-agent = %{version}-%{release} +Requires: libcynara-client-commons-devel = %{version}-%{release} + +%description -n libcynara-agent-devel +agent client library (devel) for communication with cynara service and plugins + +####################################################### %package -n libcynara-storage Summary: Cynara - storage @@ -252,6 +268,7 @@ cp -a %{SOURCE1010} . cp -a %{SOURCE1011} . cp -a %{SOURCE1012} . cp -a %{SOURCE1013} . +cp -a %{SOURCE1014} . cp -a test/db/db* . %build @@ -352,6 +369,10 @@ fi %postun -n libcynara-admin -p /sbin/ldconfig +%post -n libcynara-agent -p /sbin/ldconfig + +%postun -n libcynara-agent -p /sbin/ldconfig + %post -n libcynara-storage -p /sbin/ldconfig %postun -n libcynara-storage -p /sbin/ldconfig @@ -380,6 +401,10 @@ fi %postun -n libcynara-admin-devel -p /sbin/ldconfig +%post -n libcynara-agent-devel -p /sbin/ldconfig + +%postun -n libcynara-agent-devel -p /sbin/ldconfig + %post -n libcynara-commons-devel -p /sbin/ldconfig %postun -n libcynara-commons-devel -p /sbin/ldconfig @@ -470,6 +495,16 @@ fi %{_libdir}/libcynara-admin.so %{_libdir}/pkgconfig/cynara-admin.pc +%files -n libcynara-agent +%manifest libcynara-agent.manifest +%license LICENSE +%{_libdir}/libcynara-agent.so.* + +%files -n libcynara-agent-devel +%{_includedir}/cynara/cynara-agent.h +%{_libdir}/libcynara-agent.so +%{_libdir}/pkgconfig/cynara-agent.pc + %files -n libcynara-storage %manifest libcynara-storage.manifest %license LICENSE diff --git a/packaging/libcynara-agent.manifest b/packaging/libcynara-agent.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libcynara-agent.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index a93ae55..e37f19a 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -20,6 +20,7 @@ ADD_SUBDIRECTORY(cynara-client) ADD_SUBDIRECTORY(cynara-client-async) ADD_SUBDIRECTORY(cynara-admin) +ADD_SUBDIRECTORY(cynara-agent) ADD_SUBDIRECTORY(cynara-creds-commons) ADD_SUBDIRECTORY(cynara-creds-dbus) ADD_SUBDIRECTORY(cynara-creds-socket) diff --git a/pkgconfig/cynara-agent/CMakeLists.txt b/pkgconfig/cynara-agent/CMakeLists.txt new file mode 100644 index 0000000..7782e29 --- /dev/null +++ b/pkgconfig/cynara-agent/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @file pkgconfig/cynara-agent/CMakeLists.txt +# @author Adam Malinowski +# + +CONFIGURE_FILE(cynara-agent.pc.in cynara-agent.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-agent/cynara-agent.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig + ) diff --git a/pkgconfig/cynara-agent/cynara-agent.pc.in b/pkgconfig/cynara-agent/cynara-agent.pc.in new file mode 100644 index 0000000..363a75c --- /dev/null +++ b/pkgconfig/cynara-agent/cynara-agent.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: cynara-agent +Description: cynara-agent package +Version: @CYNARA_VERSION@ +Requires: +Libs: -L${libdir} -lcynara-agent +Cflags: -I${includedir}/cynara diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe4d096..60a8a40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,6 +49,7 @@ ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(client-async) ADD_SUBDIRECTORY(client-common) ADD_SUBDIRECTORY(admin) +ADD_SUBDIRECTORY(agent) ADD_SUBDIRECTORY(storage) ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(helpers/creds-commons) diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt new file mode 100644 index 0000000..1f31692 --- /dev/null +++ b/src/agent/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @file src/agent/CMakeLists.txt +# @author Adam Malinowski +# + +SET(LIB_CYNARA_AGENT_VERSION_MAJOR 0) +SET(LIB_CYNARA_AGENT_VERSION ${LIB_CYNARA_AGENT_VERSION_MAJOR}.3.0) + +SET(CYNARA_LIB_CYNARA_AGENT_PATH ${CYNARA_PATH}/agent) + +SET(LIB_CYNARA_AGENT_SOURCES + ${CYNARA_LIB_CYNARA_AGENT_PATH}/api/agent-api.cpp + ${CYNARA_LIB_CYNARA_AGENT_PATH}/logic/Logic.cpp + ) + +INCLUDE_DIRECTORIES( + ${CYNARA_PATH}/include + ${CYNARA_LIB_CYNARA_AGENT_PATH} + ) + +ADD_LIBRARY(${TARGET_LIB_CYNARA_AGENT} SHARED ${LIB_CYNARA_AGENT_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_LIB_CYNARA_AGENT} + PROPERTIES + SOVERSION ${LIB_CYNARA_AGENT_VERSION_MAJOR} + VERSION ${LIB_CYNARA_AGENT_VERSION} + ) + +TARGET_LINK_LIBRARIES(${TARGET_LIB_CYNARA_AGENT} + ${TARGET_CYNARA_COMMON} + ) + +INSTALL(TARGETS ${TARGET_LIB_CYNARA_AGENT} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/agent/api/ApiInterface.h b/src/agent/api/ApiInterface.h new file mode 100644 index 0000000..93c5245 --- /dev/null +++ b/src/agent/api/ApiInterface.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/agent/api/ApiInterface.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains libcynara-agent API interface definition. + */ + +#ifndef SRC_AGENT_API_APIINTERFACE_H_ +#define SRC_AGENT_API_APIINTERFACE_H_ + +#include +#include +#include +#include + +namespace Cynara { + +class ApiInterface { +public: + ApiInterface() = default; + virtual ~ApiInterface() {}; + + virtual int getRequest(AgentActionResponsePtr &actionResponsePtr) = 0; + + virtual int putResponse(AgentRequestType requestType, + ProtocolFrameSequenceNumber sequenceNumber, + const RawBuffer &pluginData) = 0; +}; + +} // namespace Cynara + +#endif /* SRC_AGENT_API_APIINTERFACE_H_ */ diff --git a/src/agent/api/agent-api.cpp b/src/agent/api/agent-api.cpp new file mode 100644 index 0000000..4baec2d --- /dev/null +++ b/src/agent/api/agent-api.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/agent/api/agent-api.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief Implementation of external libcynara-agent API + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct cynara_agent { + Cynara::ApiInterface *impl; + + cynara_agent(Cynara::ApiInterface *_impl) : impl(_impl) {} + + ~cynara_agent() { + delete impl; + } +}; + +CYNARA_API +int cynara_agent_initialize(cynara_agent **pp_cynara_agent, const char *p_agent_type) { + if (!pp_cynara_agent) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + *pp_cynara_agent = new cynara_agent(new Cynara::Logic(p_agent_type)); + + init_log(); + + LOGD("Cynara agent initialized"); + + return CYNARA_API_SUCCESS; + }); +} + +CYNARA_API +int cynara_agent_finish(cynara_agent *pp_cynara_agent) { + delete pp_cynara_agent; + + return CYNARA_API_SUCCESS; +} + +CYNARA_API +int cynara_agent_get_request(cynara_agent *p_cynara_agent, cynara_agent_msg_type *req_type, + cynara_agent_req_id *req_id, void **data, size_t *data_size) { + + if (!p_cynara_agent || !p_cynara_agent->impl) + return CYNARA_API_INVALID_PARAM; + if (!req_type || !req_id) + return CYNARA_API_INVALID_PARAM; + if (!data || !data_size) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + Cynara::AgentActionResponsePtr actionResponsePtr; + int ret = p_cynara_agent->impl->getRequest(actionResponsePtr); + if (ret != CYNARA_API_SUCCESS) + return ret; + + size_t dataSize = actionResponsePtr->data().size(); + if (dataSize > 0) { + void *tmpData = malloc(dataSize); + if (tmpData == nullptr) + return CYNARA_API_OUT_OF_MEMORY; + + *data = tmpData; + memcpy(*data, actionResponsePtr->data().data(), dataSize); + } + + *data_size = dataSize; + *req_type = static_cast(actionResponsePtr->type()); + *req_id = actionResponsePtr->sequenceNumber(); + + return CYNARA_API_SUCCESS; + }); +} + +CYNARA_API +int cynara_agent_put_response(cynara_agent *p_cynara_agent, const cynara_agent_msg_type resp_type, + const cynara_agent_req_id req_id, const void *data, + const size_t data_size) { + + if (!p_cynara_agent || !p_cynara_agent->impl) + return CYNARA_API_INVALID_PARAM; + if ((resp_type != CYNARA_MSG_TYPE_ACTION) && (resp_type != CYNARA_MSG_TYPE_CANCEL)) + return CYNARA_API_INVALID_PARAM; + if ((!data && data_size) || (data && !data_size)) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + const char *first = static_cast(data); + const char *last = first + data_size; + Cynara::RawBuffer pluginData(first, last); + return p_cynara_agent->impl->putResponse(resp_type, req_id, pluginData); + }); +} diff --git a/src/agent/logic/Logic.cpp b/src/agent/logic/Logic.cpp new file mode 100644 index 0000000..b8a66d4 --- /dev/null +++ b/src/agent/logic/Logic.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/agent/logic/Logic.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains implementation of Logic class - main libcynara-agent class + */ + +#include + +#include + +#include "Logic.h" + +namespace Cynara { + +Logic::Logic(const AgentType &agentType) : m_agentType(agentType) { +} + +int Logic::getRequest(AgentActionResponsePtr &resultPtr UNUSED) { + // TODO: implement + return CYNARA_API_SUCCESS; +} + +int Logic::putResponse(const AgentResponseType responseType UNUSED, + const ProtocolFrameSequenceNumber sequenceNumber UNUSED, + const RawBuffer &pluginData UNUSED) { + + // TODO: implement + return CYNARA_API_SUCCESS; +} + +} // namespace Cynara diff --git a/src/agent/logic/Logic.h b/src/agent/logic/Logic.h new file mode 100644 index 0000000..facead7 --- /dev/null +++ b/src/agent/logic/Logic.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * @file src/agent/logic/Logic.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file contains definition of Logic class - main libcynara-agent class + */ + +#ifndef SRC_AGENT_LOGIC_LOGIC_H_ +#define SRC_AGENT_LOGIC_LOGIC_H_ + +#include + +#include + +namespace Cynara { + +class Logic : public ApiInterface { +public: + Logic(const AgentType &agentType); + virtual ~Logic() {}; + + virtual int getRequest(AgentActionResponsePtr &actionResponsePtr); + + virtual int putResponse(const AgentResponseType responseType, + const ProtocolFrameSequenceNumber sequenceNumber, + const RawBuffer &pluginData); + +private: + AgentType m_agentType; +}; + +} // namespace Cynara + +#endif /* SRC_AGENT_LOGIC_LOGIC_H_ */ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 72b7d7f..42f66eb 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -46,6 +46,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/RequestTaker.cpp ${COMMON_PATH}/request/SetPoliciesRequest.cpp ${COMMON_PATH}/request/SignalRequest.cpp + ${COMMON_PATH}/response/AgentActionResponse.cpp ${COMMON_PATH}/response/CancelResponse.cpp ${COMMON_PATH}/response/CheckResponse.cpp ${COMMON_PATH}/response/CodeResponse.cpp diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index 5c90004..e20a6ad 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -30,6 +30,9 @@ namespace Cynara { class AdminCheckRequest; typedef std::shared_ptr AdminCheckRequestPtr; +class AgentActionRequest; +typedef std::shared_ptr AgentActionRequestPtr; + class CancelRequest; typedef std::shared_ptr CancelRequestPtr; diff --git a/src/common/response/AgentActionResponse.cpp b/src/common/response/AgentActionResponse.cpp new file mode 100644 index 0000000..4a8bcc8 --- /dev/null +++ b/src/common/response/AgentActionResponse.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/response/AgentActionResponse.cpp + * @author Adam Malinowski + * @version 1.0 + * @brief This file implements common class for sending a request to agent + */ + +#include + +#include + +#include "AgentActionResponse.h" + +namespace Cynara { + +void AgentActionResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/AgentActionResponse.h b/src/common/response/AgentActionResponse.h new file mode 100644 index 0000000..f99c043 --- /dev/null +++ b/src/common/response/AgentActionResponse.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/response/AgentActionResponse.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines class for responding to agent action request + */ + +#ifndef SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ +#define SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ + +#include +#include +#include +#include +#include + +namespace Cynara { + +class AgentActionResponse : public Response { +public: + AgentActionResponse(const AgentResponseType type, const RawBuffer &data, + ProtocolFrameSequenceNumber sequenceNumber) : Response(sequenceNumber), + m_type(type), m_data(data) {} + + ~AgentActionResponse() {} + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, RequestContextPtr context) const; + + const RawBuffer &data(void) const { + return m_data; + } + + AgentResponseType type(void) const { + return m_type; + } + +private: + const AgentResponseType m_type; + const RawBuffer m_data; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_AGENTACTIONRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index 3f558c4..34f84f5 100644 --- a/src/common/response/ResponseTaker.cpp +++ b/src/common/response/ResponseTaker.cpp @@ -28,6 +28,10 @@ namespace Cynara { +void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentActionResponsePtr response UNUSED) { + throw NotImplementedException(); +} + void ResponseTaker::execute(RequestContextPtr context UNUSED, CancelResponsePtr response UNUSED) { throw NotImplementedException(); } diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 0afdb65..1642072 100644 --- a/src/common/response/ResponseTaker.h +++ b/src/common/response/ResponseTaker.h @@ -33,6 +33,7 @@ public: ResponseTaker() = default; virtual ~ResponseTaker() {}; + virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); virtual void execute(RequestContextPtr context, CancelResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); diff --git a/src/common/response/pointers.h b/src/common/response/pointers.h index 4e9b8fc..1774a4b 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class AgentActionResponse; +typedef std::shared_ptr AgentActionResponsePtr; + class CancelResponse; typedef std::shared_ptr CancelResponsePtr; diff --git a/src/common/types/Agent.h b/src/common/types/Agent.h new file mode 100644 index 0000000..7f26af7 --- /dev/null +++ b/src/common/types/Agent.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/types/Agent.h + * @author Adam Malinowski + * @version 1.0 + * @brief This file defines agent related types + */ + +#ifndef SRC_COMMON_TYPES_AGENT_H_ +#define SRC_COMMON_TYPES_AGENT_H_ + +#include +#include + +namespace Cynara { + +typedef std::uint8_t AgentRequestType; +typedef std::uint8_t AgentResponseType; +typedef std::string AgentType; + +} // namespace Cynara + +#endif /* SRC_COMMON_TYPES_AGENT_H_ */ diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index b43bd1f..08f909c 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin.h ${CYNARA_PATH}/include/cynara-admin-types.h + ${CYNARA_PATH}/include/cynara-agent.h ${CYNARA_PATH}/include/cynara-client.h ${CYNARA_PATH}/include/cynara-client-async.h ${CYNARA_PATH}/include/cynara-client-plugin.h -- 2.7.4 From 67d6e25e9474be1b6c9d44d5534046c217ad9f11 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Wed, 12 Nov 2014 13:41:43 +0100 Subject: [PATCH 16/16] Fix answer callback call in asynchronous client Answer callback may modify check map by calling async client api functions within it. Check map is accessed after that call. Change-Id: Ifbf91f99cfa119e5524457f585b2779d7ae52558 --- src/client-async/callback/ResponseCallback.cpp | 6 ++++++ src/client-async/callback/ResponseCallback.h | 1 + src/client-async/check/CheckData.h | 5 +++++ src/client-async/logic/Logic.cpp | 6 ++++-- src/common/types/PolicyKey.h | 6 ++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp index 9307195..f904483 100644 --- a/src/client-async/callback/ResponseCallback.cpp +++ b/src/client-async/callback/ResponseCallback.cpp @@ -28,6 +28,12 @@ ResponseCallback::ResponseCallback(cynara_response_callback callback, void *user : m_callback(callback), m_userData(userData) { } +ResponseCallback::ResponseCallback(ResponseCallback &&other) + : m_callback(other.m_callback), m_userData(other.m_userData) { + other.m_callback = nullptr; + other.m_userData = nullptr; +} + void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const { if (!m_callback) return; diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h index 925d7f4..1af7291 100644 --- a/src/client-async/callback/ResponseCallback.h +++ b/src/client-async/callback/ResponseCallback.h @@ -31,6 +31,7 @@ class ResponseCallback { public: ResponseCallback(cynara_response_callback callback, void *userData); ResponseCallback(const ResponseCallback&) = default; + ResponseCallback(ResponseCallback &&other); ~ResponseCallback() {}; void onAnswer(cynara_check_id checkId, int response) const; diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h index a25abb3..453af76 100644 --- a/src/client-async/check/CheckData.h +++ b/src/client-async/check/CheckData.h @@ -38,6 +38,11 @@ class CheckData public: CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback) : m_key(key), m_session(session), m_callback(callback), m_cancelled(false) {} + CheckData(CheckData &&other) + : m_key(std::move(other.m_key)), m_session(std::move(other.m_session)), + m_callback(std::move(other.m_callback)), m_cancelled(other.m_cancelled) { + other.m_cancelled = false; + } ~CheckData() {} const PolicyKey &key(void) const { diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index bfb494c..9725d64 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -166,10 +166,12 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { } int result = m_cache->update(it->second.session(), it->second.key(), checkResponse->m_resultRef); - if (!it->second.cancelled()) - it->second.callback().onAnswer(static_cast(it->first), result); + CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); + if (!checkData.cancelled()) + checkData.callback().onAnswer( + static_cast(checkResponse->sequenceNumber()), result); } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/common/types/PolicyKey.h b/src/common/types/PolicyKey.h index 6bf0302..3f65c58 100644 --- a/src/common/types/PolicyKey.h +++ b/src/common/types/PolicyKey.h @@ -36,6 +36,9 @@ class PolicyKeyFeature { friend class PolicyKey; public: + PolicyKeyFeature(const PolicyKeyFeature &) = default; + PolicyKeyFeature(PolicyKeyFeature &&) = default; + typedef std::string ValueType; static PolicyKeyFeature create(ValueType value) { @@ -98,6 +101,9 @@ public: const PolicyKeyFeature::ValueType &privilegeId) : m_client(clientId), m_user(userId), m_privilege(privilegeId) {}; + PolicyKey(const PolicyKey &) = default; + PolicyKey(PolicyKey &&) = default; + bool operator==(const PolicyKey &other) const { return std::tie(m_client, m_user, m_privilege) == std::tie(other.m_client, other.m_user, other.m_privilege); -- 2.7.4