From 8dd72120e13a4192408b8940b85ef40d980a3fdd Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 13 Nov 2014 14:25:56 +0100 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 14/16] Fix answer callback call in asynchronous client Answer callback may modify check map by calling async client api functions within it. Check map is accessed after that call. Change-Id: Ifbf91f99cfa119e5524457f585b2779d7ae52558 --- src/client-async/callback/ResponseCallback.cpp | 6 ++++++ src/client-async/callback/ResponseCallback.h | 1 + src/client-async/check/CheckData.h | 5 +++++ src/client-async/logic/Logic.cpp | 6 ++++-- src/common/types/PolicyKey.h | 6 ++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp index 9307195..f904483 100644 --- a/src/client-async/callback/ResponseCallback.cpp +++ b/src/client-async/callback/ResponseCallback.cpp @@ -28,6 +28,12 @@ ResponseCallback::ResponseCallback(cynara_response_callback callback, void *user : m_callback(callback), m_userData(userData) { } +ResponseCallback::ResponseCallback(ResponseCallback &&other) + : m_callback(other.m_callback), m_userData(other.m_userData) { + other.m_callback = nullptr; + other.m_userData = nullptr; +} + void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const { if (!m_callback) return; diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h index 925d7f4..1af7291 100644 --- a/src/client-async/callback/ResponseCallback.h +++ b/src/client-async/callback/ResponseCallback.h @@ -31,6 +31,7 @@ class ResponseCallback { public: ResponseCallback(cynara_response_callback callback, void *userData); ResponseCallback(const ResponseCallback&) = default; + ResponseCallback(ResponseCallback &&other); ~ResponseCallback() {}; void onAnswer(cynara_check_id checkId, int response) const; diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h index a25abb3..453af76 100644 --- a/src/client-async/check/CheckData.h +++ b/src/client-async/check/CheckData.h @@ -38,6 +38,11 @@ class CheckData public: CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback) : m_key(key), m_session(session), m_callback(callback), m_cancelled(false) {} + CheckData(CheckData &&other) + : m_key(std::move(other.m_key)), m_session(std::move(other.m_session)), + m_callback(std::move(other.m_callback)), m_cancelled(other.m_cancelled) { + other.m_cancelled = false; + } ~CheckData() {} const PolicyKey &key(void) const { diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index bfb494c..9725d64 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -166,10 +166,12 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { } int result = m_cache->update(it->second.session(), it->second.key(), checkResponse->m_resultRef); - if (!it->second.cancelled()) - it->second.callback().onAnswer(static_cast(it->first), result); + CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); + if (!checkData.cancelled()) + checkData.callback().onAnswer( + static_cast(checkResponse->sequenceNumber()), result); } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/common/types/PolicyKey.h b/src/common/types/PolicyKey.h index 6bf0302..3f65c58 100644 --- a/src/common/types/PolicyKey.h +++ b/src/common/types/PolicyKey.h @@ -36,6 +36,9 @@ class PolicyKeyFeature { friend class PolicyKey; public: + PolicyKeyFeature(const PolicyKeyFeature &) = default; + PolicyKeyFeature(PolicyKeyFeature &&) = default; + typedef std::string ValueType; static PolicyKeyFeature create(ValueType value) { @@ -98,6 +101,9 @@ public: const PolicyKeyFeature::ValueType &privilegeId) : m_client(clientId), m_user(userId), m_privilege(privilegeId) {}; + PolicyKey(const PolicyKey &) = default; + PolicyKey(PolicyKey &&) = default; + bool operator==(const PolicyKey &other) const { return std::tie(m_client, m_user, m_privilege) == std::tie(other.m_client, other.m_user, other.m_privilege); -- 2.7.4 From a62008b94c1460be31fa9fc53f784c0d5fcbd1a7 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 13:18:32 +0100 Subject: [PATCH 15/16] Forbid some operations in asynchronous callbacks In following cases cynara api operations regarding same cynara_async structure called from within callbacks will return CYNARA_API_OPERATION_NOT_ALLOWED: - always within cynara_status_callback - within cynara_response_callback called with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause. It regards following api funtions: - cynara_async_check_cache() - cynara_async_create_request() - cynara_async_process() - cynara_async_cancel_request() Change-Id: I1db22e0735e1905c4709c7f4c650cc8ca3f9b454 --- src/client-async/logic/Logic.cpp | 42 +++++++++++++++++++++++++++++---------- src/client-async/logic/Logic.h | 2 ++ src/include/cynara-client-async.h | 19 +++++++++++++++--- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 9725d64..5e0157d 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,7 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -55,6 +55,7 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) } Logic::~Logic() { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onFinish(kv.first); @@ -64,6 +65,9 @@ Logic::~Logic() { int Logic::checkCache(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!checkCacheValid()) return CYNARA_API_CACHE_MISS; @@ -74,6 +78,9 @@ int Logic::createRequest(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege, cynara_check_id &checkId, cynara_response_callback callback, void *userResponseData) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -86,14 +93,16 @@ int Logic::createRequest(const std::string &client, const std::string &session, m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback))); m_socketClient->appendRequest(std::make_shared(key, sequenceNumber)); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); checkId = static_cast(sequenceNumber); return CYNARA_API_SUCCESS; } int Logic::process(void) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + bool completed; while (true) { int ret = completeConnection(completed); @@ -108,6 +117,9 @@ int Logic::process(void) { } int Logic::cancelRequest(cynara_check_id checkId) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -119,8 +131,7 @@ int Logic::cancelRequest(cynara_check_id checkId) { it->second.cancel(); it->second.callback().onCancel(it->first); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } @@ -144,8 +155,8 @@ void Logic::prepareRequestsToSend(void) { bool Logic::processOut(void) { switch (m_socketClient->sendToCynara()) { case Socket::SendStatus::ALL_DATA_SENT: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_READ); + onStatusChange(m_socketClient->getSockFd(), + cynara_async_status::CYNARA_STATUS_FOR_READ); case Socket::SendStatus::PARTIAL_DATA_SENT: return true; default: @@ -238,12 +249,11 @@ bool Logic::connect(void) { switch (m_socketClient->connect()) { case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); return true; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return true; default: onServiceNotAvailable(); @@ -257,7 +267,7 @@ int Logic::completeConnection(bool &completed) { completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: @@ -271,19 +281,29 @@ int Logic::completeConnection(bool &completed) { } } +void Logic::onStatusChange(int sock, cynara_async_status status) { + m_operationPermitted = false; + m_statusCallback.onStatusChange(sock, status); + m_operationPermitted = true; +} + void Logic::onServiceNotAvailable(void) { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onDisconnected(kv.first); } m_checks.clear(); m_sequenceContainer.clear(); + m_operationPermitted = true; } void Logic::onDisconnected(void) { + m_operationPermitted = false; m_cache->clear(); m_statusCallback.onDisconnected(); + m_operationPermitted = true; } } // namespace Cynara diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 0bca98e..6f30fdb 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -59,6 +59,7 @@ private: SocketClientAsyncPtr m_socketClient; CheckMap m_checks; SequenceContainer m_sequenceContainer; + bool m_operationPermitted; bool checkCacheValid(void); void prepareRequestsToSend(void); @@ -71,6 +72,7 @@ private: bool ensureConnection(void); bool connect(void); int completeConnection(bool &completed); + void onStatusChange(int sock, cynara_async_status status); void onServiceNotAvailable(void); void onDisconnected(void); }; diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index 536e5d7..b9675f1 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -84,6 +84,8 @@ typedef enum { * (CYNARA_CALL_CAUSE_FINISH) * 4) when connection to cynara service was broken and cannot be established again * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) + * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -113,6 +115,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * Note, that provided file descriptor is used internally by libcynara * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. + * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -240,7 +243,10 @@ void cynara_async_finish(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_check_cache() needs cynara_async structure to be created first. - * Use cynara_async_initialize() before calling this function. + * Use cynara_async_initialize() before calling this function. cynara_async_check_cache() called + * from within cynara_status_callback or cynara_response_callback with + * CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause will return + * CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -306,6 +312,9 @@ int cynara_async_check_cache(cynara_async *p_cynara, const char *client, const c * If function fails (returns negative error code) request won't be generated and won't be pending, * callback function won't be ever called and user_response_data won't be remembered by library. * Also no check_id will be generated and *p_check_id value should be ignored. + * cynara_async_create_request() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -359,7 +368,9 @@ int cynara_async_create_request(cynara_async *p_cynara, const char *client, * * \par Important notes: * Call to cynara_async_process() requires initialized cynara_async structure. For this use - * cynara_async_initialize(). + * cynara_async_initialize(). cynara_async_process() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * @@ -398,7 +409,9 @@ int cynara_async_process(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_cancel_request() needs cynara_async structure to be created first. For this - * use cynara_async_initialize(). + * use cynara_async_initialize(). cynara_async_cancel_request() called from within + * cynara_status_callback or cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] check_id Check id to be cancelled -- 2.7.4 From bf838ebf47eabea59dae47d83f1fdc360693f5cb Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 18:48:01 +0100 Subject: [PATCH 16/16] Add protection against cynara_async_finish() call in callbacks cynara_async_finish() called in callbacks is ignored in all cases. Change-Id: I3c2268a0462413b279215f837e4603a7d6acb96d --- src/client-async/api/ApiInterface.h | 1 + src/client-async/api/client-async-api.cpp | 3 +++ src/client-async/logic/Logic.cpp | 18 ++++++++++++++++-- src/client-async/logic/Logic.h | 2 ++ src/include/cynara-client-async.h | 4 ++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/client-async/api/ApiInterface.h b/src/client-async/api/ApiInterface.h index 31478da..59c82fb 100644 --- a/src/client-async/api/ApiInterface.h +++ b/src/client-async/api/ApiInterface.h @@ -42,6 +42,7 @@ public: void *userResponseData) = 0; virtual int process(void) = 0; virtual int cancelRequest(cynara_check_id checkId) = 0; + virtual bool isFinishPermitted(void) = 0; }; } // namespace Cynara diff --git a/src/client-async/api/client-async-api.cpp b/src/client-async/api/client-async-api.cpp index 1e3479e..13e5a16 100644 --- a/src/client-async/api/client-async-api.cpp +++ b/src/client-async/api/client-async-api.cpp @@ -61,6 +61,9 @@ int cynara_async_initialize(cynara_async **pp_cynara, CYNARA_API void cynara_async_finish(cynara_async *p_cynara) { + if (!p_cynara->impl->isFinishPermitted()) + return; + delete p_cynara; } diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 5e0157d..48b8bad 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,8 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true), + m_inAnswerCancelResponseCallback(false) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -130,12 +131,21 @@ int Logic::cancelRequest(cynara_check_id checkId) { m_socketClient->appendRequest(std::make_shared(it->first)); it->second.cancel(); + + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; it->second.callback().onCancel(it->first); + m_inAnswerCancelResponseCallback = onAnswerCancel; + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } +bool Logic::isFinishPermitted(void) { + return m_operationPermitted && !m_inAnswerCancelResponseCallback; +} + bool Logic::checkCacheValid(void) { return m_socketClient->isConnected(); } @@ -180,9 +190,13 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); - if (!checkData.cancelled()) + if (!checkData.cancelled()) { + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; checkData.callback().onAnswer( static_cast(checkResponse->sequenceNumber()), result); + m_inAnswerCancelResponseCallback = onAnswerCancel; + } } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 6f30fdb..6d41412 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -49,6 +49,7 @@ public: void *userResponseData); virtual int process(void); virtual int cancelRequest(cynara_check_id checkId); + virtual bool isFinishPermitted(void); private: typedef std::map CheckMap; @@ -60,6 +61,7 @@ private: CheckMap m_checks; SequenceContainer m_sequenceContainer; bool m_operationPermitted; + bool m_inAnswerCancelResponseCallback; bool checkCacheValid(void); void prepareRequestsToSend(void); diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index b9675f1..d9b4d2f 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -86,6 +86,7 @@ typedef enum { * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -116,6 +117,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -207,6 +209,8 @@ int cynara_async_initialize(cynara_async **pp_cynara, const cynara_async_configu * * \par Important notes: * No other call to cynara-async-client library should be made after call to cynara_async_finish(). + * cynara_async_finish() called from within cynara_response_callback or cynara_status_callback will + * be ignored. * * \param[in] p_cynara cynara_async structure. If NULL, then the call has no effect. */ -- 2.7.4