Asynchronous API framework 37/29037/1
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 16 Sep 2014 07:52:27 +0000 (09:52 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Thu, 16 Oct 2014 15:10:21 +0000 (17:10 +0200)
Single API function implementation. Connection thread implementation. Request
structure added.

Change-Id: Ic823b8c1dcc713edda9273a5c5cbe7763182e150

13 files changed:
packaging/key-manager.spec
src/CMakeLists.txt
src/include/ckm/ckm-manager-async.h [new file with mode: 0644]
src/include/ckm/ckm-manager.h
src/manager/client-async/async-request.cpp [new file with mode: 0644]
src/manager/client-async/async-request.h [new file with mode: 0644]
src/manager/client-async/client-manager-async-impl.cpp [new file with mode: 0644]
src/manager/client-async/client-manager-async-impl.h [new file with mode: 0644]
src/manager/client-async/client-manager-async.cpp [new file with mode: 0644]
src/manager/client-async/connection-thread.cpp [new file with mode: 0644]
src/manager/client-async/connection-thread.h [new file with mode: 0644]
src/manager/common/descriptor-set.cpp
src/manager/common/descriptor-set.h

index 62e53fc..4d17bd6 100644 (file)
@@ -207,6 +207,7 @@ fi
 %{_libdir}/libkey-manager-control-client.so
 %{_libdir}/libkey-manager-common.so
 %{_includedir}/ckm/ckm/ckm-manager.h
+%{_includedir}/ckm/ckm/ckm-manager-async.h
 %{_includedir}/ckm/ckm/ckm-certificate.h
 %{_includedir}/ckm/ckm/ckm-control.h
 %{_includedir}/ckm/ckm/ckm-error.h
index 943bb27..5063236 100644 (file)
@@ -64,10 +64,12 @@ SET(KEY_MANAGER_CLIENT_VERSION_MAJOR 1)
 SET(KEY_MANAGER_CLIENT_VERSION ${KEY_MANAGER_CLIENT_VERSION_MAJOR}.0.1)
 
 SET(KEY_MANAGER_CLIENT_SRC_PATH ${KEY_MANAGER_PATH}/client)
+SET(KEY_MANAGER_CLIENT_ASYNC_SRC_PATH ${KEY_MANAGER_PATH}/client-async)
 SET(KEY_MANAGER_CLIENT_CAPI_SRC_PATH ${KEY_MANAGER_PATH}/client-capi)
 
 INCLUDE_DIRECTORIES(
     ${KEY_MANAGER_PATH}/client
+    ${KEY_MANAGER_PATH}/client-async
     ${KEY_MANAGER_PATH}/client-capi
     ${KEY_MANAGER_PATH}/common
     ${KEY_MANAGER_PATH}/dpl/core/include
@@ -78,6 +80,10 @@ SET(KEY_MANAGER_CLIENT_SOURCES
     ${KEY_MANAGER_CLIENT_SRC_PATH}/client-common.cpp
     ${KEY_MANAGER_CLIENT_SRC_PATH}/client-error.cpp
     ${KEY_MANAGER_CLIENT_SRC_PATH}/client-manager-impl.cpp
+    ${KEY_MANAGER_CLIENT_ASYNC_SRC_PATH}/client-manager-async.cpp
+    ${KEY_MANAGER_CLIENT_ASYNC_SRC_PATH}/client-manager-async-impl.cpp
+    ${KEY_MANAGER_CLIENT_ASYNC_SRC_PATH}/connection-thread.cpp
+    ${KEY_MANAGER_CLIENT_ASYNC_SRC_PATH}/async-request.cpp
     ${KEY_MANAGER_CLIENT_CAPI_SRC_PATH}/ckmc-type.cpp
     ${KEY_MANAGER_CLIENT_CAPI_SRC_PATH}/ckmc-error.cpp
     ${KEY_MANAGER_CLIENT_CAPI_SRC_PATH}/ckmc-manager.cpp
@@ -146,6 +152,7 @@ INSTALL(TARGETS ${TARGET_KEY_MANAGER} DESTINATION bin)
 
 INSTALL(FILES
     ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-manager.h
+    ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-manager-async.h
     ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-certificate.h
     ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-control.h
     ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-error.h
diff --git a/src/include/ckm/ckm-manager-async.h b/src/include/ckm/ckm-manager-async.h
new file mode 100644 (file)
index 0000000..a6dcc3d
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  Copyright (c) 2000 - 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        ckm-manager-async.h
+ * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version     1.0
+ * @brief       Async key manager API.
+ */
+#pragma once
+
+#include <memory>
+
+#include <ckm/ckm-certificate.h>
+#include <ckm/ckm-error.h>
+#include <ckm/ckm-key.h>
+#include <ckm/ckm-type.h>
+
+// Central Key Manager namespace
+namespace CKM {
+
+// Asynchronous interface to Central Key Manager. This implementation uses
+// internal thread for connection. Key Manager is not thread safe.
+class ManagerAsync
+{
+public:
+    class Impl;
+
+    ManagerAsync();
+
+    ManagerAsync(const ManagerAsync&) = delete;
+    ManagerAsync& operator=(const ManagerAsync&) = delete;
+
+    // Observer will observer custom operation.
+    struct Observer {
+        // Error callback - all errors
+        // ERROR_API_NOT_SUPPORTED,
+        // ERROR_API_CONNECTION_LOST,
+        // ERROR_API_PARSING_ERROR,
+        // ERROR_API_ALIAS_UNKNOWN
+        virtual void ReceivedError(int error) = 0;
+
+        virtual void ReceivedSaveKey() {}
+
+        // This will return data
+        /*
+        virtual void ReceivedKey(Key && key) {}
+        virtual void ReceivedCertificate(Certificate && certificate) {}
+        virtual void ReceivedKeyAliasVector(AliasVector && aliasVector) {}
+        virtual void ReceivedCertificateAliasVector(AliasVector && aliasVector) {}
+
+        // This callbacks will confirm successful operation
+        virtual void ReceivedSaveCertificate() {}
+        virtual void ReceivedRemovedKey() {}
+        virtual void ReceivedRemovedCertificate() {}
+
+        // Added By Dongsun Lee
+        virtual void ReceivedData(RawBuffer && data) {}
+        virtual void ReceivedDataAliasVector(AliasVector && aliasVector) {}
+
+        // This callbacks will confirm successful operation
+        virtual void ReceivedSaveData() {}
+        virtual void ReceivedRemovedData() {}
+        virtual void ReceivedCreateKeyPairRSA() {}
+        virtual void ReceivedCreateKeyPairECDSA() {}
+        virtual void ReceivedCreateSignature(RawBuffer && signature) {}
+
+        // TODO: describe status
+        virtual void ReceivedVerifySignature() {}
+        // TODO: describe status
+        // Do we need some chain of the certificate?
+        virtual void ReceivedVerifyCertificate() {}
+
+        virtual void ReceivedGetCertiticateChain(CertificateShPtrVector &&certificateVector) {}
+        virtual void ReceivedStrictCACheck();
+        virtual void ReceivedOCSPCheck();*/
+
+        virtual ~Observer() {}
+    };
+
+    typedef std::shared_ptr<Observer> ObserverPtr;
+
+    virtual ~ManagerAsync();
+
+    void saveKey(const ObserverPtr& observer, const Alias& alias, const KeyShPtr& key, const Policy& policy);
+
+    /*
+    void saveCertificate(Observer *observer, const Alias &alias, const Certificate &cert, const Policy &policy);
+
+    void removeKey(Observer *observer, const Alias &alias);
+    void removeCertificate(Observer *observer, const Alias &alias);
+
+    void requestKey(Observer *observer, const Alias &alias);
+    void requestCertificate(Observer *observer, const Alias &alias);
+
+    // This will extract list of all Keys and Certificates in Key Store
+    void requestKeyAliasVector(Observer *observer);         // send request for list of all keys that application/user may use
+    void requestCertificateAliasVector(Observer *observer); // send request for list of all certs that application/user may use
+
+    // Added By Dongsun Lee
+    void saveData(Observer *observer, const Alias &alias, const RawBuffer &data, const Policy &policy);
+    void removeData(Observer *observer, const Alias &alias);
+    void requestData(Observer *observer, const Alias &alias);
+    void requestDataAliasVector(Observer *observer);  // send request for list of all data that application/user may use
+    void createKeyPairRSA(Observer *observer, const Alias &privateKeyAlias, const Alias &publicKeyAlias, const int &size, const Policy &policy);
+    void createKeyPairECDSA(Observer *observer, const Alias &privateKeyAlias, const Alias &publicKeyAlias, ECType type, const int &size, const Policy &policy);
+    void createSignature(Observer *observer, const Alias &privateKeyAlias, const RawBuffer &password, const RawBuffer &message);
+    void verifySignature(Observer *observer, const Alias &publicKeyOrCertAlias, const RawBuffer &password, const RawBuffer &message, const RawBuffer &signature);
+
+    // Should we use also certificates stored by user in Certral Key Manager?
+    // Sometimes we may want to verify certificate without OCSP (for example we are installing side-loaded app and network is not working).
+    void verifyCertificate(Observer *observer, const Certificate &certificate, const CertificateShPtrVector &untrusted, const bool ocspCheck, const bool strictCaFlagCheck);
+
+    void createKeyPairRSA(
+    Observer *observer,
+    const int size,              // size in bits [1024, 2048, 4096]
+    const Alias &privateKeyAlias,
+    const Alias &publicKeyAlias,
+    const Policy &policyPrivateKey = Policy(),
+    const Policy &policyPublicKey = Policy());
+
+    void createKeyPairECDSA(
+    Observer *observer,
+    const Key::ECType type,
+    const Alias &privateKeyAlias,
+    const Alias &publicKeyAlias,
+    const Policy &policyPrivateKey = Policy(),
+    const Policy &policyPublicKey = Policy());
+
+    // this fuction will return chains of certificates and check it with openssl
+    // status : OK, INCOMPLETE_CHAIN, VERIFICATION_FAILED
+    void getCertiticateChain(
+    const Certificate &certificate,
+    const CertificateShPtrVector &untrustedCertificates);
+
+    void getCertificateChain(
+    const Certificate &certificate,
+    const AliasVector &untrustedCertificates);
+
+    void strictCACheck(const CertificateShPtrVector &certificateVector);
+
+    // This function will check all certificates in chain except Root CA.
+    void ocspCheck(const CertificateShPtrVector &certificateChainVector);*/
+
+private:
+    std::unique_ptr<Impl> m_impl;
+};
+
+// Out of scope
+/*
+ class ManagerAsyncNoThread : public ManagerAsync {
+ public:
+     ManagerAsyncNoThread();
+     ManagerAsyncNoThread(const ConnectionAsyncNoThread &);
+     ManagerAsyncNoThread(ConnectionAsyncNoThread &&);
+     ManagerAsyncNoThread& operator=(const ConnectionAsyncNoThread &);
+     ManagerAsyncNoThread& operator=(ConnectionAsyncNoThread &&);
+     virtual ~ConnecitonAsyncNoThread() {}
+
+     int getDesc();          // extract descriptor number
+     int processDesc();      // send request and receive data from central key manager
+     };
+ */
+
+} // namespace CKM
+
index 24185ec..5c4e96f 100644 (file)
@@ -125,154 +125,5 @@ public:
 //    static ManagerShPtr getManager(int uid); // TODO
 };
 
-/*
-// Asynchronous interface to Central Key Manager. This implementation uses
-// internal thread for connection.
-class ManagerAsync {
-public:
-    class ManagerAsyncImpl;
-
-    // Observer will observer custom operation.
-    struct Observer {
-        // Error callback - all errors
-               // ERROR_API_NOT_SUPPORTED,
-               // ERROR_API_CONNECTION_LOST,
-               // ERROR_API_PARSING_ERROR,
-               // ERROR_API_ALIAS_UNKNOWN
-        virtual void ReceivedError(int error, const std::string &errormsg);
-
-        // This will return data
-        virtual void ReceivedKey(Key && key) {}
-        virtual void ReceivedCertificate(Certificate && certificate) {}
-        virtual void ReceivedKeyAliasVector(AliasVector && aliasVector) {}
-        virtual void ReceivedCertificateAliasVector(AliasVector && aliasVector) {}
-
-        // This callbacks will confirm successful operation
-        virtual void ReceivedSaveKey() {}
-        virtual void ReceivedSaveCertificate() {}
-        virtual void ReceivedRemovedKey() {}
-        virtual void ReceivedRemovedCertificate() {}
-
-        // Added By Dongsun Lee
-        virtual void ReceivedData(RawBuffer && data) {}
-        virtual void ReceivedDataAliasVector(AliasVector && aliasVector) {}
-
-        // This callbacks will confirm successful operation
-        virtual void ReceivedSaveData() {}
-        virtual void ReceivedRemovedData() {}
-        virtual void ReceivedCreateKeyPairRSA() {}
-               virtual void ReceivedCreateKeyPairECDSA() {}
-        virtual void ReceivedCreateSignature(RawBuffer && signature) {}
-
-        // TODO: describe status
-        virtual void ReceivedVerifySignature() {}
-        // TODO: describe status
-        // Do we need some chain of the certificate?
-        virtual void ReceivedVerifyCertificate() {}
-
-               virtual void ReceivedGetCertiticateChain(CertificateShPtrVector &&certificateVector) {}
-               virtual void ReceivedStrictCACheck();
-               virtual void ReceivedOCSPCheck();
-
-               virtual ~Observer() {}
-    };
-
-    ManagerAsync();
-    ManagerAsync(const ManagerAsync &);
-    ManagerAsync(ManagerAsync &&);
-    ManagerAsync& operator=(const ManagerAsync &);
-    ManagerAsync& operator=(ManagerAsync &&);
-    virtual ~ManagerAsync();
-
-    // observer will be destroyed after use
-    void saveKey(Observer *observer, const Alias &alias, const Key &key, const Policy &policy);
-    void saveCertificate(Observer *observer, const Alias &alias, const Certificate &cert, const Policy &policy);
-
-    void removeKey(Observer *observer, const Alias &alias);
-    void removeCertificate(Observer *observer, const Alias &alias);
-
-    void requestKey(Observer *observer, const Alias &alias);
-    void requestCertificate(Observer *observer, const Alias &alias);
-
-    // This will extract list of all Keys and Certificates in Key Store
-    void requestKeyAliasVector(Observer *observer);         // send request for list of all keys that application/user may use
-    void requestCertificateAliasVector(Observer *observer); // send request for list of all certs that application/user may use
-
-    // Added By Dongsun Lee
-    void saveData(Observer *observer, const Alias &alias, const RawBuffer &data, const Policy &policy);
-    void removeData(Observer *observer, const Alias &alias);
-    void requestData(Observer *observer, const Alias &alias);
-    void requestDataAliasVector(Observer *observer);  // send request for list of all data that application/user may use
-    void createKeyPairRSA(Observer *observer, const Alias &privateKeyAlias, const Alias &publicKeyAlias, const int &size, const Policy &policy);
-       void createKeyPairECDSA(Observer *observer, const Alias &privateKeyAlias, const Alias &publicKeyAlias, ECType type, const int &size, const Policy &policy);
-    void createSignature(Observer *observer, const Alias &privateKeyAlias, const RawBuffer &password, const RawBuffer &message);
-    void verifySignature(Observer *observer, const Alias &publicKeyOrCertAlias, const RawBuffer &password, const RawBuffer &message, const RawBuffer &signature);
-
-    // Should we use also certificates stored by user in Certral Key Manager?
-    // Sometimes we may want to verify certificate without OCSP (for example we are installing side-loaded app and network is not working).
-    void verifyCertificate(Observer *observer, const Certificate &certificate, const CertificateShPtrVector &untrusted, const bool ocspCheck, const bool strictCaFlagCheck);
-
-       void createKeyPairRSA(
-                       Observer *observer,
-                       const int size,              // size in bits [1024, 2048, 4096]
-                       const Alias &privateKeyAlias,
-                       const Alias &publicKeyAlias,
-                       const Policy &policyPrivateKey = Policy(),
-                       const Policy &policyPublicKey = Policy());
-
-       void createKeyPairECDSA(
-                       Observer *observer,
-                       const Key::ECType type,
-                       const Alias &privateKeyAlias,
-                       const Alias &publicKeyAlias,
-                       const Policy &policyPrivateKey = Policy(),
-                       const Policy &policyPublicKey = Policy());
-
-       // this fuction will return chains of certificates and check it with openssl
-       // status : OK, INCOMPLETE_CHAIN, VERIFICATION_FAILED
-       void getCertiticateChain(
-                       const Certificate &certificate,
-                       const CertificateShPtrVector &untrustedCertificates);
-
-       void getCertificateChain(
-                       const Certificate &certificate,
-                       const AliasVector &untrustedCertificates);
-
-       void strictCACheck(const CertificateShPtrVector &certificateVector);
-
-       // This function will check all certificates in chain except Root CA.
-       void ocspCheck(const CertificateShPtrVector &certificateChainVector);
-
-private:
-    ConnectionAsyncImpl *m_impl;
-};
-
-class ManagerAsyncThread : public ManagerAsync {
-public:
-    ManagerAsyncThread();
-       ManagerAsyncThread(int uid); // connect to database related to uid
-    ManagerAsyncThread(const ConnectionAsyncThread &);
-    ManagerAsyncThread(ConnectionAsyncThread &&);
-    ManagerAsyncThread& operator=(const ConnectionAsyncThread &);
-    ManagerAsyncThread& operator=(ConnectionAsyncThread &&);
-    virtual ~ConnectionAsyncThread() {}
-};
-*/
-// Out of scope
-/*
-class ManagerAsyncNoThread : public ManagerAsync {
-public:
-    ManagerAsyncNoThread();
-    ManagerAsyncNoThread(const ConnectionAsyncNoThread &);
-    ManagerAsyncNoThread(ConnectionAsyncNoThread &&);
-    ManagerAsyncNoThread& operator=(const ConnectionAsyncNoThread &);
-    ManagerAsyncNoThread& operator=(ConnectionAsyncNoThread &&);
-    virtual ~ConnecitonAsyncNoThread() {}
-
-    int getDesc();          // extract descriptor number
-    int processDesc();      // send request and receive data from central key manager
-};
-*/
-
 } // namespace CKM
 
diff --git a/src/manager/client-async/async-request.cpp b/src/manager/client-async/async-request.cpp
new file mode 100644 (file)
index 0000000..554028d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (c) 2000 - 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       async-request.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <async-request.h>
+#include <utility>
+
+namespace CKM {
+
+AsyncRequest::AsyncRequest(const ManagerAsync::ObserverPtr& o,
+                           std::string&& i,
+                           RawBuffer&& b,
+                           int id) :
+    observer(o),
+    interface(std::move(i)),
+    buffer(std::move(b)),
+    written(0),
+    id(id)
+{
+}
+
+} /* namespace CKM */
diff --git a/src/manager/client-async/async-request.h b/src/manager/client-async/async-request.h
new file mode 100644 (file)
index 0000000..7c5330a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2000 - 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       async-request.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <string>
+#include <map>
+#include <queue>
+#include <list>
+#include <ckm/ckm-raw-buffer.h>
+#include <ckm/ckm-manager-async.h>
+
+namespace CKM {
+
+struct AsyncRequest
+{
+    typedef std::map<int, AsyncRequest> Map;
+    typedef std::queue<AsyncRequest, std::list<AsyncRequest> > Queue;
+
+    AsyncRequest(const ManagerAsync::ObserverPtr& observer,
+                 std::string&& interface,
+                 RawBuffer&& buffer,
+                 int id);
+
+    ManagerAsync::ObserverPtr observer;
+    std::string interface;
+    RawBuffer buffer;
+    size_t written;
+    int id;
+};
+
+} /* namespace CKM */
diff --git a/src/manager/client-async/client-manager-async-impl.cpp b/src/manager/client-async/client-manager-async-impl.cpp
new file mode 100644 (file)
index 0000000..744e3a2
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (c) 2000 - 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       client-manager-async-impl.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <client-manager-async-impl.h>
+#include <ckm/ckm-error.h>
+#include <message-buffer.h>
+#include <client-common.h>
+#include <stdexcept>
+
+namespace CKM {
+
+int ManagerAsync::Impl::m_counter = 0;
+
+ManagerAsync::Impl::Impl()
+{
+}
+
+ManagerAsync::Impl::~Impl()
+{
+}
+
+void ManagerAsync::Impl::saveKey(const ManagerAsync::ObserverPtr& observer,
+                                 const Alias& alias,
+                                 const KeyShPtr& key,
+                                 const Policy& policy)
+{
+    observerCheck(observer);
+
+    if (!key) {
+        observer->ReceivedError(CKM_API_ERROR_INPUT_PARAM);
+        return;
+    }
+    saveBinaryData(observer, alias, toDBDataType(key->getType()), key->getDER(), policy);
+}
+
+void ManagerAsync::Impl::saveBinaryData(const ManagerAsync::ObserverPtr& observer,
+                                        const Alias& alias,
+                                        DBDataType dataType,
+                                        const RawBuffer& rawData,
+                                        const Policy& policy)
+{
+    if (alias.empty() || rawData.empty()) {
+        observer->ReceivedError(CKM_API_ERROR_INPUT_PARAM);
+        return;
+    }
+
+    try_catch_async([&] {
+        m_counter++;
+
+        MessageBuffer send;
+        Serialization::Serialize(send, static_cast<int>(LogicCommand::SAVE));
+        Serialization::Serialize(send, m_counter);
+        Serialization::Serialize(send, static_cast<int>(dataType));
+        Serialization::Serialize(send, alias);
+        Serialization::Serialize(send, rawData);
+        Serialization::Serialize(send, PolicySerializable(policy));
+
+        thread()->sendMessage(AsyncRequest(observer,
+                                           SERVICE_SOCKET_CKM_STORAGE,
+                                           send.Pop(),
+                                           m_counter));
+
+    }, [&observer](int error){ observer->ReceivedError(error); } );
+}
+
+void ManagerAsync::Impl::observerCheck(const ManagerAsync::ObserverPtr& observer)
+{
+    if(!observer)
+        throw std::invalid_argument("Empty observer");
+}
+
+} // namespace CKM
diff --git a/src/manager/client-async/client-manager-async-impl.h b/src/manager/client-async/client-manager-async-impl.h
new file mode 100644 (file)
index 0000000..e3fde09
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2000 - 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       client-manager-async-impl.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <ckm/ckm-manager-async.h>
+#include <memory>
+#include <connection-thread.h>
+#include <protocols.h>
+#include <noncopyable.h>
+
+namespace CKM {
+
+class ManagerAsync::Impl
+{
+public:
+    Impl();
+
+    NONCOPYABLE(Impl);
+
+    virtual ~Impl();
+
+    void saveKey(const ManagerAsync::ObserverPtr&, const Alias&, const KeyShPtr&, const Policy&);
+
+private:
+    void saveBinaryData(const ManagerAsync::ObserverPtr& observer,
+                        const Alias& alias,
+                        DBDataType dataType,
+                        const RawBuffer& rawData,
+                        const Policy& policy);
+
+    void observerCheck(const ManagerAsync::ObserverPtr& observer);
+
+    typedef std::unique_ptr<ConnectionThread> ConnectionThreadPtr;
+
+    ConnectionThreadPtr& thread() {
+        if (!m_thread || m_thread->finished()) {
+            m_thread.reset(new ConnectionThread());
+            m_thread->run();
+        }
+        return m_thread;
+    }
+
+    ConnectionThreadPtr m_thread;
+
+    static int m_counter;
+};
+
+} // namespace CKM
diff --git a/src/manager/client-async/client-manager-async.cpp b/src/manager/client-async/client-manager-async.cpp
new file mode 100644 (file)
index 0000000..85f376f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2000 - 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       client-manager-async.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <ckm/ckm-manager-async.h>
+#include <client-manager-async-impl.h>
+
+namespace CKM {
+
+ManagerAsync::ManagerAsync()
+{
+    m_impl.reset(new Impl());
+}
+
+ManagerAsync::~ManagerAsync()
+{
+    m_impl.reset();
+}
+
+void ManagerAsync::saveKey(const ObserverPtr& observer,
+                           const Alias& alias,
+                           const KeyShPtr& key,
+                           const Policy& policy)
+{
+    m_impl->saveKey(observer, alias, key, policy);
+}
+
+} // namespace CKM
+
diff --git a/src/manager/client-async/connection-thread.cpp b/src/manager/client-async/connection-thread.cpp
new file mode 100644 (file)
index 0000000..d6ea9be
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (c) 2000 - 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       connection-thread.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <connection-thread.h>
+#include <unistd.h>
+#include <poll.h>
+#include <dpl/log/log.h>
+#include <client-common.h>
+
+namespace CKM {
+
+namespace {
+const int POLL_TIMEOUT = 8000;
+} // namespace anonymous
+
+ConnectionThread::Pipe::Pipe()
+{
+    if (-1 == pipe(m_pipe))
+        ThrowMsg(PipeError, "Pipe creation failed " << strerror(errno));
+}
+
+ConnectionThread::Pipe::~Pipe()
+{
+    close(m_pipe[0]);
+    close(m_pipe[1]);
+}
+
+void ConnectionThread::Pipe::notify()
+{
+    if (-1 == TEMP_FAILURE_RETRY(write(m_pipe[1],"j",1)))
+        ThrowMsg(PipeError, "Writing pipe failed " << strerror(errno));
+}
+
+ConnectionThread::ConnectionThread() :
+    m_join(false),
+    m_finished(false)
+{
+}
+
+ConnectionThread::~ConnectionThread() {
+    m_join = true;
+    m_pipe.notify();
+    m_thread.join();
+}
+
+void ConnectionThread::run() {
+    m_thread = std::thread(&ConnectionThread::threadLoop, this);
+}
+
+void ConnectionThread::sendMessage(AsyncRequest&& req) {
+    std::unique_lock<std::mutex> lock(m_mutex);
+    m_waitingReqs.push(std::move(req));
+    lock.unlock();
+
+    // notifty via pipe
+    m_pipe.notify();
+}
+
+void ConnectionThread::threadLoop()
+{
+    try {
+        m_descriptors.add(m_pipe.output(),
+                          POLLIN,
+                          [this](int fd, short revents){ newRequest(fd, revents); });
+
+        while (!m_join) {
+            // wait for pipe/socket notification
+            m_descriptors.wait();
+        }
+    } catch (CKM::Exception &e) {
+        LogError("CKM::Exception::Exception " << e.DumpToString());
+    } catch (std::exception &e) {
+        LogError("STD exception " << e.what());
+    } catch (...) {
+        LogError("Unknown exception occured");
+    }
+
+    // close all descriptors (including pipe)
+    m_descriptors.purge();
+
+    // remove waiting requests and notify about error
+    std::unique_lock<std::mutex> lock(m_mutex);
+    while(!m_waitingReqs.empty()) {
+        m_waitingReqs.front().observer->ReceivedError(CKM_API_ERROR_UNKNOWN);
+        m_waitingReqs.pop();
+    }
+    lock.unlock();
+
+    m_finished = true;
+}
+
+void ConnectionThread::readPipe(int pipe, short revents)
+{
+    char buffer[1];
+
+    if ((revents & POLLIN) == 0)
+        ThrowMsg(PipeError, "Unexpected event: " << revents << "!=" << POLLIN);
+
+    if(1 != TEMP_FAILURE_RETRY(read(pipe,buffer, 1))) {
+        int err = errno;
+        ThrowMsg(PipeError, "Failed to read pipe: " << strerror(err));
+    }
+}
+
+void ConnectionThread::newRequest(int pipe, short revents)
+{
+    readPipe(pipe, revents);
+
+    std::unique_lock<std::mutex> lock(m_mutex);
+
+    // nothing to do?
+    if(m_waitingReqs.empty()) {
+        LogWarning("Empty request queue. Are we exiting?");
+        return;
+    }
+
+    // zero-copy remove
+    AsyncRequest req = std::move(m_waitingReqs.front());
+    m_waitingReqs.pop();
+
+    lock.unlock();
+
+    // TODO handle request here
+    req.observer->ReceivedError(CKM_API_ERROR_UNKNOWN);
+}
+
+} /* namespace CKM */
diff --git a/src/manager/client-async/connection-thread.h b/src/manager/client-async/connection-thread.h
new file mode 100644 (file)
index 0000000..864000d
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2000 - 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       connection-thread.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <thread>
+#include <mutex>
+#include <string>
+#include <dpl/exception.h>
+#include <noncopyable.h>
+#include <client-common.h>
+#include <async-request.h>
+#include <descriptor-set.h>
+
+namespace CKM {
+
+class ConnectionThread
+{
+public:
+    DECLARE_EXCEPTION_TYPE(CKM::Exception, PipeError)
+
+    ConnectionThread();
+    virtual ~ConnectionThread();
+
+    NONCOPYABLE(ConnectionThread);
+
+    void run();
+
+    void sendMessage(AsyncRequest&& request);
+
+    bool finished() const { return m_finished; }
+
+private:
+    void threadLoop();
+
+    void newRequest(int pipe, short revents);
+
+    // reads notification pipe
+    void readPipe(int pipe, short revents);
+
+    // Helper class that creates a pipe before thread is started
+    class Pipe {
+    public:
+        Pipe();
+        ~Pipe();
+
+        NONCOPYABLE(Pipe);
+
+        void notify();
+        int output() const { return m_pipe[0]; }
+
+    private:
+        int m_pipe[2];
+    };
+    // shared vars
+    Pipe m_pipe;
+    AsyncRequest::Queue m_waitingReqs;
+    std::mutex m_mutex;
+    bool m_join;
+    bool m_finished;
+
+    // parent thread vars
+    std::thread m_thread;
+
+    // child thread vars
+    DescriptorSet m_descriptors;
+};
+
+} /* namespace CKM */
index e32e4ec..9312c73 100644 (file)
@@ -51,9 +51,10 @@ void DescriptorSet::add(int fd, short events, Callback&& callback) {
     m_dirty = true;
 }
 
-void DescriptorSet::remove(int fd) {
+void DescriptorSet::remove(int fd, bool close_fd) {
     if (0 != m_descriptors.erase(fd)) {
-        close(fd);
+        if (close_fd)
+            close(fd);
         m_dirty = true;
     }
 }
index c6a0a4e..7e166ba 100644 (file)
@@ -36,7 +36,7 @@ public:
     typedef std::function<void(int, short)> Callback;
 
     virtual void add(int fd, short events, Callback&& callback) = 0;
-    virtual void remove(int fd) = 0;
+    virtual void remove(int fd, bool close_fd = true) = 0;
 protected:
     // I don't want anyone to manage object lifetime via interface.
     IDescriptorSet() {}
@@ -69,7 +69,7 @@ public:
      *
      * @param fd       descriptor to be removed and closed
      */
-    virtual void remove(int fd);
+    virtual void remove(int fd, bool close_fd = true);
 
     /*
      * Wait for descriptor events using poll().