SET(LIB_CYNARA_ASYNC_SOURCES
${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp
+ ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/ResponseCallback.cpp
${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/StatusCallback.cpp
${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp
+ ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sequence/SequenceContainer.cpp
${CYNARA_LIB_CYNARA_ASYNC_PATH}/sockets/SocketClientAsync.cpp
)
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/client-async/callback/ResponseCallback.cpp
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.0
+ * @brief This file contains definition of ResponseCallback class
+ */
+
+#include "ResponseCallback.h"
+
+namespace Cynara {
+
+ResponseCallback::ResponseCallback(cynara_response_callback callback, void *userData)
+ : m_callback(callback), m_userData(userData) {
+}
+
+void ResponseCallback::onAnswer(cynara_check_id checkId, int response) const {
+ if (!m_callback)
+ return;
+ m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_ANSWER, response, m_userData);
+}
+
+void ResponseCallback::onFinish(cynara_check_id checkId) const {
+ if (!m_callback)
+ return;
+ m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_FINISH, 0, m_userData);
+}
+
+void ResponseCallback::onDisconnected(cynara_check_id checkId) const {
+ if (!m_callback)
+ return;
+ m_callback(checkId, cynara_async_call_cause::CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE, 0,
+ m_userData);
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/client-async/callback/ResponseCallback.h
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.0
+ * @brief This file contains declaration of ResponseCallback class
+ */
+
+#ifndef SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_
+#define SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_
+
+#include <cynara-client-async.h>
+
+namespace Cynara {
+
+class ResponseCallback {
+public:
+ ResponseCallback(cynara_response_callback callback, void *userData);
+ ResponseCallback(const ResponseCallback&) = default;
+ ~ResponseCallback() {};
+
+ void onAnswer(cynara_check_id checkId, int response) const;
+ // MOCKUP
+ void onFinish(cynara_check_id checkId) const;
+ void onDisconnected(cynara_check_id checkId) const;
+
+private:
+ cynara_response_callback m_callback;
+ void *m_userData;
+};
+
+} // namespace Cynara
+
+#endif /* SRC_CLIENT_ASYNC_CALLBACK_RESPONSECALLBACK_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/client-async/check/CheckData.h
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.0
+ * @brief This file contains CheckData class for storing
+ * information about asynchronous check request.
+ */
+
+#ifndef SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_
+#define SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_
+
+#include <memory>
+#include <string>
+
+#include <types/PolicyKey.h>
+
+#include <callback/ResponseCallback.h>
+
+namespace Cynara {
+
+class CheckData
+{
+public:
+ CheckData(const PolicyKey &key, const std::string &session, const ResponseCallback &callback)
+ : m_key(key), m_session(session), m_callback(callback) {}
+ ~CheckData() {}
+
+ const PolicyKey &key(void) const {
+ return m_key;
+ }
+
+ const std::string &session(void) const {
+ return m_session;
+ }
+
+ const ResponseCallback &callback(void) const {
+ return m_callback;
+ }
+
+private:
+ PolicyKey m_key;
+ std::string m_session;
+ ResponseCallback m_callback;
+ // MOCKUP
+};
+
+} // namespace Cynara
+
+#endif // SRC_CLIENT_ASYNC_CHECK_CHECKDATA_H_
+
#include <cache/CapacityCache.h>
#include <common.h>
#include <exceptions/Exception.h>
+#include <exceptions/NoMemoryException.h>
#include <exceptions/UnexpectedErrorException.h>
#include <log/log.h>
#include <plugins/NaiveInterpreter.h>
#include <protocol/ProtocolClient.h>
+#include <request/CheckRequest.h>
+#include <response/CheckResponse.h>
#include <sockets/Socket.h>
#include <sockets/SocketPath.h>
}
Logic::~Logic() {
- onDisconnected();
+ for (auto &kv : m_checks)
+ kv.second.callback().onFinish(kv.first);
+ m_statusCallback.onDisconnected();
}
int Logic::checkCache(const std::string &client, const std::string &session,
return m_cache->get(session, PolicyKey(client, user, privilege));
}
-int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED,
- const std::string &user UNUSED, const std::string &privilege UNUSED,
- cynara_check_id &checkId UNUSED, cynara_response_callback callback UNUSED,
- void *userResponseData UNUSED) {
+int Logic::createRequest(const std::string &client, const std::string &session,
+ const std::string &user, const std::string &privilege,
+ cynara_check_id &checkId, cynara_response_callback callback,
+ void *userResponseData) {
if (!ensureConnection())
return CYNARA_API_SERVICE_NOT_AVAILABLE;
- // MOCKUP
- return CYNARA_API_MAX_PENDING_REQUESTS;
+ ProtocolFrameSequenceNumber sequenceNumber;
+ if (!m_sequenceContainer.get(sequenceNumber))
+ return CYNARA_API_MAX_PENDING_REQUESTS;
+
+ PolicyKey key(client, user, privilege);
+ ResponseCallback responseCallback(callback, userResponseData);
+ m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback)));
+ m_socketClient->appendRequest(std::make_shared<CheckRequest>(key, sequenceNumber));
+
+ m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
+ cynara_async_status::CYNARA_STATUS_FOR_RW);
+ checkId = static_cast<cynara_check_id>(sequenceNumber);
+
+ return CYNARA_API_SUCCESS;
}
int Logic::process(void) {
bool completed;
- int ret = completeConnection(completed);
- if (!completed)
- return ret;
-
- // MOCKUP
- return CYNARA_API_SUCCESS;
+ while (true) {
+ int ret = completeConnection(completed);
+ if (!completed)
+ return ret;
+ if (processOut() && processIn())
+ return CYNARA_API_SUCCESS;
+ onDisconnected();
+ if (!connect())
+ return CYNARA_API_SERVICE_NOT_AVAILABLE;
+ }
}
int Logic::cancelRequest(cynara_check_id checkId UNUSED) {
}
void Logic::prepareRequestsToSend(void) {
+ for (auto &kv : m_checks) {
+ // MOCKUP
+ m_socketClient->appendRequest(std::make_shared<CheckRequest>(kv.second.key(), kv.first));
+ }
+}
+
+bool Logic::processOut(void) {
+ switch (m_socketClient->sendToCynara()) {
+ case Socket::SendStatus::ALL_DATA_SENT:
+ m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
+ cynara_async_status::CYNARA_STATUS_FOR_READ);
+ case Socket::SendStatus::PARTIAL_DATA_SENT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void Logic::processCheckResponse(CheckResponsePtr checkResponse) {
+ LOGD("checkResponse: policyType = [%" PRIu16 "], metadata = <%s>",
+ checkResponse->m_resultRef.policyType(),
+ checkResponse->m_resultRef.metadata().c_str());
+
+ auto it = m_checks.find(checkResponse->sequenceNumber());
+ if (it == m_checks.end()) {
+ LOGC("Critical error. Unknown response received: sequenceNumber = [%" PRIu16 "]",
+ checkResponse->sequenceNumber());
+ throw UnexpectedErrorException("Unexpected response from cynara service");
+ }
+ int result = m_cache->update(it->second.session(), it->second.key(),
+ checkResponse->m_resultRef);
// MOCKUP
+ it->second.callback().onAnswer(static_cast<cynara_check_id>(it->first), result);
+ m_sequenceContainer.release(it->first);
+ m_checks.erase(it);
+}
+
+void Logic::processResponses(void) {
+ ResponsePtr response;
+ CheckResponsePtr checkResponse;
+ while (true) {
+ response = m_socketClient->getResponse();
+ if (!response)
+ break;
+
+ checkResponse = std::dynamic_pointer_cast<CheckResponse>(response);
+ if (checkResponse) {
+ processCheckResponse(checkResponse);
+ continue;
+ }
+ // MOCKUP
+ LOGC("Critical error. Casting Response to CheckResponse failed.");
+ throw UnexpectedErrorException("Unexpected response from cynara service");
+ }
+}
+
+bool Logic::processIn(void) {
+ if (!m_socketClient->receiveFromCynara())
+ return false;
+ processResponses();
+ return true;
}
cynara_async_status Logic::socketDataStatus(void) {
if (m_socketClient->isConnected())
return true;
onDisconnected();
+
+ return connect();
+}
+
+bool Logic::connect(void) {
switch (m_socketClient->connect()) {
case Socket::ConnectionStatus::CONNECTION_SUCCEEDED:
prepareRequestsToSend();
cynara_async_status::CYNARA_STATUS_FOR_RW);
return true;
default:
+ onServiceNotAvailable();
return false;
}
}
default:
completed = false;
onDisconnected();
+ onServiceNotAvailable();
return CYNARA_API_SERVICE_NOT_AVAILABLE;
}
}
+void Logic::onServiceNotAvailable(void)
+{
+ for (auto &kv : m_checks)
+ kv.second.callback().onDisconnected(kv.first);
+ m_checks.clear();
+ m_sequenceContainer.clear();
+}
+
void Logic::onDisconnected(void) {
m_cache->clear();
m_statusCallback.onDisconnected();
#define SRC_CLIENT_ASYNC_LOGIC_LOGIC_H_
#include <cache/CacheInterface.h>
+#include <types/ProtocolFields.h>
#include <api/ApiInterface.h>
#include <callback/StatusCallback.h>
+#include <check/CheckData.h>
#include <cynara-client-async.h>
+#include <sequence/SequenceContainer.h>
#include <sockets/SocketClientAsync.h>
namespace Cynara {
virtual int cancelRequest(cynara_check_id checkId);
private:
+ typedef std::map<ProtocolFrameSequenceNumber, CheckData> CheckMap;
+ typedef std::pair<ProtocolFrameSequenceNumber, CheckData> CheckPair;
+
StatusCallback m_statusCallback;
PluginCachePtr m_cache;
SocketClientAsyncPtr m_socketClient;
+ CheckMap m_checks;
+ SequenceContainer m_sequenceContainer;
bool checkCacheValid(void);
void prepareRequestsToSend(void);
cynara_async_status socketDataStatus(void);
+ bool processOut(void);
+ void processCheckResponse(CheckResponsePtr checkResponse);
+ void processResponses(void);
+ bool processIn(void);
bool ensureConnection(void);
+ bool connect(void);
int completeConnection(bool &completed);
+ void onServiceNotAvailable(void);
void onDisconnected(void);
};
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/client-async/sequence/SequenceContainer.cpp
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.0
+ * @brief This file contains definition of SequenceContainer class for
+ * storing check requests identifiers in libcynara-client-async
+ */
+
+#include <algorithm>
+#include <cinttypes>
+#include <climits>
+#include <cstring>
+
+#include "SequenceContainer.h"
+
+namespace Cynara {
+
+SequenceContainer::SequenceContainer()
+ : m_sequenceVector(((static_cast<size_t>(UINT16_MAX) + 1) / CHAR_BIT) / sizeof(int), -1) {
+}
+
+bool SequenceContainer::get(ProtocolFrameSequenceNumber &sequenceNumber) {
+ for (size_t index = 0; index < m_sequenceVector.size(); ++index) {
+ int pos = ffs(m_sequenceVector[index]);
+ if (pos != 0) {
+ sequenceNumber = static_cast<uint16_t>(index * sizeof(int) * CHAR_BIT - 1 + pos);
+ m_sequenceVector[index] ^= 1 << (pos - 1);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SequenceContainer::release(ProtocolFrameSequenceNumber sequenceNumber) {
+ size_t index = static_cast<size_t>(sequenceNumber) / (CHAR_BIT * sizeof(int));
+ int pos = static_cast<int>(sequenceNumber) % (CHAR_BIT * sizeof(int));
+ int i = m_sequenceVector[index] | 1 << pos;
+ if (i == m_sequenceVector[index])
+ return false;
+ m_sequenceVector[index] = i;
+ return true;
+}
+
+void SequenceContainer::clear(void) {
+ memset(m_sequenceVector.data(), -1, m_sequenceVector.size() * sizeof(int));
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/client-async/sequence/SequenceContainer.h
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.0
+ * @brief This file contains declaration of SequenceContainer class for
+ * storing check requests identifiers in libcynara-client-async
+ */
+
+#ifndef SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_
+#define SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_
+
+#include <vector>
+
+#include <types/ProtocolFields.h>
+
+namespace Cynara {
+
+class SequenceContainer {
+public:
+ SequenceContainer();
+ ~SequenceContainer() {}
+
+ bool get(ProtocolFrameSequenceNumber &sequenceNumber);
+ bool release(ProtocolFrameSequenceNumber sequenceNumber);
+ void clear(void);
+
+private:
+ std::vector<int> m_sequenceVector;
+};
+
+} // namespace Cynara
+
+#endif // SRC_CLIENT_ASYNC_SEQUENCE_SEQUENCECONTAINER_H_