Add creating, sending and receiving check requests 85/28285/7
authorMarcin Niesluchowski <m.niesluchow@samsung.com>
Thu, 18 Sep 2014 09:32:15 +0000 (11:32 +0200)
committerMarcin Niesluchowski <m.niesluchow@samsung.com>
Mon, 13 Oct 2014 17:13:39 +0000 (19:13 +0200)
cynara_async_create_request() and cynara_async_process() functions work
according to the API header excluding possibility to cancel request.

Change-Id: I9818be674d58da5bd431a08b7faf47dfe0157289

src/client-async/CMakeLists.txt
src/client-async/callback/ResponseCallback.cpp [new file with mode: 0644]
src/client-async/callback/ResponseCallback.h [new file with mode: 0644]
src/client-async/check/CheckData.h [new file with mode: 0644]
src/client-async/logic/Logic.cpp
src/client-async/logic/Logic.h
src/client-async/sequence/SequenceContainer.cpp [new file with mode: 0644]
src/client-async/sequence/SequenceContainer.h [new file with mode: 0644]

index 5b3d404..a9b9971 100644 (file)
@@ -30,8 +30,10 @@ INCLUDE_DIRECTORIES(
 
 SET(LIB_CYNARA_ASYNC_SOURCES
     ${CYNARA_LIB_CYNARA_ASYNC_PATH}/api/client-async-api.cpp
+    ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/ResponseCallback.cpp
     ${CYNARA_LIB_CYNARA_ASYNC_PATH}/callback/StatusCallback.cpp
     ${CYNARA_LIB_CYNARA_ASYNC_PATH}/logic/Logic.cpp
+    ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sequence/SequenceContainer.cpp
     ${CYNARA_LIB_CYNARA_ASYNC_PATH}/sockets/SocketClientAsync.cpp
     )
 
diff --git a/src/client-async/callback/ResponseCallback.cpp b/src/client-async/callback/ResponseCallback.cpp
new file mode 100644 (file)
index 0000000..e4577b3
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/client-async/callback/ResponseCallback.cpp
+ * @author      Marcin Niesluchowski <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
diff --git a/src/client-async/callback/ResponseCallback.h b/src/client-async/callback/ResponseCallback.h
new file mode 100644 (file)
index 0000000..47d526a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/client-async/callback/ResponseCallback.h
+ * @author      Marcin Niesluchowski <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_ */
diff --git a/src/client-async/check/CheckData.h b/src/client-async/check/CheckData.h
new file mode 100644 (file)
index 0000000..1f8fe90
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/client-async/check/CheckData.h
+ * @author      Marcin Niesluchowski <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_
+
index e1574ce..23cd7cc 100644 (file)
 #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>
 
@@ -49,7 +52,9 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData)
 }
 
 Logic::~Logic() {
-    onDisconnected();
+    for (auto &kv : m_checks)
+        kv.second.callback().onFinish(kv.first);
+    m_statusCallback.onDisconnected();
 }
 
 int Logic::checkCache(const std::string &client, const std::string &session,
@@ -60,25 +65,41 @@ int Logic::checkCache(const std::string &client, const std::string &session,
     return m_cache->get(session, PolicyKey(client, user, privilege));
 }
 
-int Logic::createRequest(const std::string &client UNUSED, const std::string &session UNUSED,
-                         const std::string &user UNUSED, const std::string &privilege UNUSED,
-                         cynara_check_id &checkId UNUSED, cynara_response_callback callback UNUSED,
-                         void *userResponseData UNUSED) {
+int Logic::createRequest(const std::string &client, const std::string &session,
+                         const std::string &user, const std::string &privilege,
+                         cynara_check_id &checkId, cynara_response_callback callback,
+                         void *userResponseData) {
     if (!ensureConnection())
         return CYNARA_API_SERVICE_NOT_AVAILABLE;
 
-    // MOCKUP
-    return CYNARA_API_MAX_PENDING_REQUESTS;
+    ProtocolFrameSequenceNumber sequenceNumber;
+    if (!m_sequenceContainer.get(sequenceNumber))
+        return CYNARA_API_MAX_PENDING_REQUESTS;
+
+    PolicyKey key(client, user, privilege);
+    ResponseCallback responseCallback(callback, userResponseData);
+    m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback)));
+    m_socketClient->appendRequest(std::make_shared<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) {
@@ -94,7 +115,67 @@ bool Logic::checkCacheValid(void) {
 }
 
 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) {
@@ -106,6 +187,11 @@ bool Logic::ensureConnection(void) {
     if (m_socketClient->isConnected())
         return true;
     onDisconnected();
+
+    return connect();
+}
+
+bool Logic::connect(void) {
     switch (m_socketClient->connect()) {
         case Socket::ConnectionStatus::CONNECTION_SUCCEEDED:
             prepareRequestsToSend();
@@ -117,6 +203,7 @@ bool Logic::ensureConnection(void) {
                                             cynara_async_status::CYNARA_STATUS_FOR_RW);
             return true;
         default:
+            onServiceNotAvailable();
             return false;
     }
 }
@@ -136,10 +223,19 @@ int Logic::completeConnection(bool &completed) {
         default:
             completed = false;
             onDisconnected();
+            onServiceNotAvailable();
             return CYNARA_API_SERVICE_NOT_AVAILABLE;
     }
 }
 
+void Logic::onServiceNotAvailable(void)
+{
+    for (auto &kv : m_checks)
+        kv.second.callback().onDisconnected(kv.first);
+    m_checks.clear();
+    m_sequenceContainer.clear();
+}
+
 void Logic::onDisconnected(void) {
     m_cache->clear();
     m_statusCallback.onDisconnected();
index 0475b08..53cfba9 100644 (file)
 #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 {
@@ -48,15 +51,26 @@ public:
     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);
 };
 
diff --git a/src/client-async/sequence/SequenceContainer.cpp b/src/client-async/sequence/SequenceContainer.cpp
new file mode 100644 (file)
index 0000000..95b9318
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/client-async/sequence/SequenceContainer.cpp
+ * @author      Marcin Niesluchowski <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
diff --git a/src/client-async/sequence/SequenceContainer.h b/src/client-async/sequence/SequenceContainer.h
new file mode 100644 (file)
index 0000000..c8748e6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/client-async/sequence/SequenceContainer.h
+ * @author      Marcin Niesluchowski <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_