diff options
-rw-r--r-- | packaging/webapi-plugins-teec.spec | 2 | ||||
-rw-r--r-- | src/teec/TeecContext.cc | 117 | ||||
-rw-r--r-- | src/teec/TeecContext.h | 69 | ||||
-rw-r--r-- | src/teec/TeecManager.cc | 74 | ||||
-rw-r--r-- | src/teec/TeecManager.h | 68 | ||||
-rw-r--r-- | src/teec/TeecSession.cc | 84 | ||||
-rw-r--r-- | src/teec/TeecSession.h | 51 | ||||
-rw-r--r-- | src/teec/TeecSharedMemory.cc | 93 | ||||
-rw-r--r-- | src/teec/TeecSharedMemory.h | 54 | ||||
-rw-r--r-- | src/teec/TeecTempMemoryAllocator.cc | 39 | ||||
-rw-r--r-- | src/teec/TeecTempMemoryAllocator.h | 52 | ||||
-rw-r--r-- | src/teec/TeecTranslations.cc | 379 | ||||
-rw-r--r-- | src/teec/TeecTranslations.h | 52 | ||||
-rw-r--r-- | src/teec/libteec_api.js | 269 | ||||
-rw-r--r-- | src/teec/libteec_extension.cc | 5 | ||||
-rw-r--r-- | src/teec/libteec_extension.h | 5 | ||||
-rw-r--r-- | src/teec/libteec_instance.cc | 415 | ||||
-rw-r--r-- | src/teec/libteec_instance.h | 31 | ||||
-rw-r--r-- | src/teec/teec.gyp | 14 |
19 files changed, 1635 insertions, 238 deletions
diff --git a/packaging/webapi-plugins-teec.spec b/packaging/webapi-plugins-teec.spec index 4a0ea10..04ae34b 100644 --- a/packaging/webapi-plugins-teec.spec +++ b/packaging/webapi-plugins-teec.spec @@ -25,7 +25,7 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: ninja BuildRequires: pkgconfig(webapi-plugins) -BuildRequires: tef-libteec +BuildRequires: pkgconfig(tef-libteec) %description Tizen TEF Framework Client API plugin diff --git a/src/teec/TeecContext.cc b/src/teec/TeecContext.cc new file mode 100644 index 0000000..280db24 --- /dev/null +++ b/src/teec/TeecContext.cc @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecContext class methods definition + */ + +#include "TeecContext.h" +#include "TeecTranslations.h" + +#include <algorithm> +#include <common/platform_exception.h> + + +namespace { + +// removes all dashes from UUID string to unify it (if there are any) +std::string UnifyUUID(const std::string& uuid) { + std::string result = uuid; + result.erase(std::remove(result.begin(), result.end(), '-'), result.end()); + return result; +} + +// generates new ID for shared memory +std::string GenerateShmemID() { + static uint64_t counter = 0; + return "shmem-" + std::to_string(counter++); +} + +} // namespace + +namespace extension { +namespace libteec { + +TeecContext::TeecContext(const std::string& name) { + TEEC_Result ret = TEEC_InitializeContext(name.empty() ? NULL : name.c_str(), &mContext); + if (ret != TEEC_SUCCESS) { + throw common::NotSupportedException("Failed to initialize context: " + + translations::TeecResultToString(ret)); + } +} + +TeecContext::~TeecContext() { + mSessions.clear(); + mSharedMemories.clear(); + TEEC_FinalizeContext(&mContext); +} + +std::string TeecContext::OpenSession(const std::string& uuidstr, uint32_t connectionMethod, + const void* connectionData, TEEC_Operation* operation, + uint32_t* returnOrigin) { + std::string uuid = UnifyUUID(uuidstr); + auto it = mSessions.find(uuid); + if (it == mSessions.end()) { + mSessions.emplace(uuid, std::make_shared<TeecSession>(&mContext, uuid, connectionMethod, + connectionData, operation, returnOrigin)); + return uuid; + } else { + throw common::InvalidValuesException("Session for TA " + uuidstr + " already exists"); + } +} + +TeecSessionPtr TeecContext::GetSession(const std::string& id) const { + std::string uuid = UnifyUUID(id); + auto it = mSessions.find(uuid); + if (it == mSessions.end()) { + throw common::InvalidValuesException("Session for TA " + id + " does not exist"); + } + + return it->second; +} + +void TeecContext::CloseSession(const std::string& id) { + std::string uuid = UnifyUUID(id); + mSessions.erase(uuid); +} + +std::string TeecContext::CreateSharedMemory(size_t size, uint32_t flags) { + std::string id = GenerateShmemID(); + mSharedMemories.emplace(id, std::make_shared<TeecSharedMemory>(&mContext, size, flags)); + return id; +} + +std::string TeecContext::CreateSharedMemory(void* buffer, size_t size, uint32_t flags) { + std::string id = GenerateShmemID(); + mSharedMemories.emplace(id, std::make_shared<TeecSharedMemory>(&mContext, buffer, size, flags)); + return id; +} + +TeecSharedMemoryPtr TeecContext::GetSharedMemory(const std::string& memId) const { + auto it = mSharedMemories.find(memId); + if (it == mSharedMemories.end()) { + throw common::InvalidValuesException("Shared memory " + memId + " does not exist"); + } + return it->second; +} + +void TeecContext::ReleaseSharedMemory(const std::string& memId) { + mSharedMemories.erase(memId); +} + +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecContext.h b/src/teec/TeecContext.h new file mode 100644 index 0000000..2a5f73f --- /dev/null +++ b/src/teec/TeecContext.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecContext class declaration + */ + +#ifndef LIBTEEC_TEEC_CONTEXT_H_ +#define LIBTEEC_TEEC_CONTEXT_H_ + +#include "TeecSession.h" +#include "TeecSharedMemory.h" + +#include <unordered_map> +#include <string> +#include <tee_client_api.h> + + +namespace extension { +namespace libteec { + +using TeecSessionMap = std::unordered_map<std::string, TeecSessionPtr>; +using TeecSharedMemoryMap = std::unordered_map<std::string, TeecSharedMemoryPtr>; + +class TeecContext final +{ +public: + TeecContext(const std::string& id); + ~TeecContext(); + + // returns session ID used to recognize sessions in GetSession and CloseSession + std::string OpenSession(const std::string& uuidstr, uint32_t connectionMethod, + const void* connectionData, TEEC_Operation* operation, + uint32_t* returnOrigin); + TeecSessionPtr GetSession(const std::string& id) const; + void CloseSession(const std::string& id); + + // returns memory ID used to recognise the memory further down the road + std::string CreateSharedMemory(size_t size, uint32_t flags); + std::string CreateSharedMemory(void* buffer, size_t size, uint32_t flags); + TeecSharedMemoryPtr GetSharedMemory(const std::string& memId) const; + void ReleaseSharedMemory(const std::string& memId); + +private: + TEEC_Context mContext; + TeecSessionMap mSessions; + TeecSharedMemoryMap mSharedMemories; +}; + +using TeecContextPtr = std::shared_ptr<TeecContext>; + +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_CONTEXT_H_
\ No newline at end of file diff --git a/src/teec/TeecManager.cc b/src/teec/TeecManager.cc new file mode 100644 index 0000000..826f20b --- /dev/null +++ b/src/teec/TeecManager.cc @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecManager singleton class methods definition + */ + +#include "TeecManager.h" + +#include <common/platform_exception.h> + + +namespace { + +static uint32_t opIDCounter = 0; + +} // namespace + +namespace extension { +namespace libteec { + +TeecManager& TeecManager::Instance() { + static TeecManager manager; + return manager; +} + +TeecContextPtr TeecManager::GetContext(const std::string& contextName) { + auto it = mContexts.find(contextName); + if (it == mContexts.end()) { + // no context - create new + TeecContextPtr context = std::make_shared<TeecContext>(contextName); + it = mContexts.insert(std::make_pair(contextName, context)).first; + } + + return it->second; +} + +uint32_t TeecManager::CreateOperation() { + std::lock_guard<std::mutex> lock(mOperationListMutex); + opIDCounter++; + mOperations.emplace(opIDCounter, TEEC_Operation()); + return opIDCounter; +} + +TEEC_Operation TeecManager::GetOperation(uint32_t id) const { + std::lock_guard<std::mutex> lock(mOperationListMutex); + auto it = mOperations.find(id); + if (it == mOperations.end()) { + throw common::InvalidValuesException("Operation " + std::to_string(id) + " not found"); + } + return it->second; +} + +void TeecManager::RemoveOperation(uint32_t id) { + std::lock_guard<std::mutex> lock(mOperationListMutex); + mOperations.erase(id); +} + +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecManager.h b/src/teec/TeecManager.h new file mode 100644 index 0000000..c7cc768 --- /dev/null +++ b/src/teec/TeecManager.h @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecManager singleton class declaration + */ + +#ifndef LIBTEEC_TEEC_MANAGER_H_ +#define LIBTEEC_TEEC_MANAGER_H_ + +#include <unordered_map> +#include <list> +#include <string> +#include <memory> +#include <mutex> +#include <tee_client_api.h> + +#include "TeecContext.h" + + +namespace extension { +namespace libteec { + +using TeecContextMap = std::unordered_map<std::string, TeecContextPtr>; +using TeecOperationMap = std::unordered_map<uint32_t, TEEC_Operation>; + +class TeecManager final +{ +public: + static TeecManager& Instance(); + + TeecContextPtr GetContext(const std::string& contextName); + + uint32_t CreateOperation(); + TEEC_Operation GetOperation(uint32_t id) const; + void RemoveOperation(uint32_t id); + +private: + TeecManager() = default; + ~TeecManager() = default; + TeecManager(const TeecManager&) = delete; + TeecManager(TeecManager&&) = delete; + TeecManager& operator=(const TeecManager&) = delete; + TeecManager& operator=(TeecManager&&) = delete; + + TeecContextMap mContexts; + TeecOperationMap mOperations; + mutable std::mutex mOperationListMutex; +}; + +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_MANAGER_H_
\ No newline at end of file diff --git a/src/teec/TeecSession.cc b/src/teec/TeecSession.cc new file mode 100644 index 0000000..8917652 --- /dev/null +++ b/src/teec/TeecSession.cc @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecSession class methods definition + */ + +#include "TeecSession.h" +#include "TeecTranslations.h" + +#include "common/logger.h" +#include "common/platform_exception.h" + + +namespace { + +const uint32_t UUID_UNIFIED_LENGTH = 32; + +// assumes UUID already was unified by TeecContext +TEEC_UUID StringToUUID(const std::string& uuidstr) { + if (uuidstr.size() != UUID_UNIFIED_LENGTH) { + throw common::InvalidValuesException("Bad UUID provided: " + uuidstr); + } + + TEEC_UUID uuid; + uuid.timeLow = std::stoul(uuidstr.substr(0, 8), 0, 16); + uuid.timeMid = static_cast<uint16_t>(std::stoul(uuidstr.substr(8, 4), 0, 16)); + uuid.timeHiAndVersion = static_cast<uint16_t>(std::stoul(uuidstr.substr(12, 4), 0, 16)); + + uint32_t stringPos = 16; + for (uint32_t i = 0; i < 8; ++i) { + uuid.clockSeqAndNode[i] = static_cast<uint8_t>(std::stoul(uuidstr.substr(stringPos, 2), 0, 16)); + stringPos += 2; + } + + return uuid; +} + +} // namespace + +namespace extension { +namespace libteec { + +TeecSession::TeecSession(TEEC_Context* ctx, const std::string& uuidstr, + uint32_t connectionMethod, const void* connectionData, + TEEC_Operation* operation, uint32_t* returnOrigin) { + TEEC_UUID uuid = StringToUUID(uuidstr); + TEEC_Result result = TEEC_OpenSession(ctx, &mSession, &uuid, connectionMethod, + connectionData, operation, returnOrigin); + if (result != TEEC_SUCCESS) { + throw common::InvalidValuesException("TEEC Session failed to open: " + + translations::TeecResultToString(result)); + } +} + +TeecSession::~TeecSession() { + TEEC_CloseSession(&mSession); +} + +void TeecSession::InvokeCommand(uint32_t cmd, TEEC_Operation* op, uint32_t* returnOrigin) { + TEEC_Result result = TEEC_InvokeCommand(&mSession, cmd, op, returnOrigin); + if (result != TEEC_SUCCESS) { + throw common::InvalidValuesException("Failure while invoking command " + + std::to_string(cmd) + ": " + + translations::TeecResultToString(result)); + } +} + +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecSession.h b/src/teec/TeecSession.h new file mode 100644 index 0000000..141c427 --- /dev/null +++ b/src/teec/TeecSession.h @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecSession class declaration + */ + +#ifndef LIBTEEC_TEEC_SESSION_H_ +#define LIBTEEC_TEEC_SESSION_H_ + +#include <string> +#include <memory> +#include <tee_client_api.h> + +namespace extension { +namespace libteec { + +class TeecSession final +{ +public: + TeecSession(TEEC_Context* ctx, const std::string& uuidstr, + uint32_t connectionMethod, const void* connectionData, + TEEC_Operation* operation, uint32_t* returnOrigin); + ~TeecSession(); + + void InvokeCommand(uint32_t cmd, TEEC_Operation* op, uint32_t* returnOrigin); + +private: + TEEC_Session mSession; +}; + +using TeecSessionPtr = std::shared_ptr<TeecSession>; + +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_SESSION_H_
\ No newline at end of file diff --git a/src/teec/TeecSharedMemory.cc b/src/teec/TeecSharedMemory.cc new file mode 100644 index 0000000..438bb79 --- /dev/null +++ b/src/teec/TeecSharedMemory.cc @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecSharedMemory class methods definition + */ + +#include "TeecSharedMemory.h" +#include "TeecTranslations.h" + +#include <string> +#include "common/platform_exception.h" + + +namespace extension { +namespace libteec { + +TeecSharedMemory::TeecSharedMemory(TEEC_Context* ctx, size_t size, uint32_t flags) { + mMemory.buffer = nullptr; + mMemory.size = size; + mMemory.flags = flags; + TEEC_Result result = TEEC_AllocateSharedMemory(ctx, &mMemory); + if (result != TEEC_SUCCESS) { + throw common::InvalidValuesException("Failed to allocate shared memory: " + + translations::TeecResultToString(result) + + " (size " + std::to_string(size) + + ", flags: " + std::to_string(flags)); + } +} + +TeecSharedMemory::TeecSharedMemory(TEEC_Context* ctx, void* buffer, size_t size, uint32_t flags) { + mMemory.buffer = buffer; + mMemory.size = size; + mMemory.flags = flags; + TEEC_Result result = TEEC_RegisterSharedMemory(ctx, &mMemory); + if (result != TEEC_SUCCESS) { + throw common::InvalidValuesException("Failed to allocate shared memory: " + + translations::TeecResultToString(result) + + " (size " + std::to_string(size) + + ", flags: " + std::to_string(flags)); + } +} + +TeecSharedMemory::~TeecSharedMemory() { + TEEC_ReleaseSharedMemory(&mMemory); +} + +void TeecSharedMemory::SetData(const DataBuffer& data, size_t offset) { + if (data.size() > (mMemory.size - offset)) { + throw common::TypeMismatchException("Not enough memory to set data: " + + std::to_string(data.size()) + + " requested, available " + + std::to_string(mMemory.size - offset) + + " at offset " + std::to_string(offset)); + } + + char* sharedBuffer = reinterpret_cast<char*>(mMemory.buffer); + memcpy(sharedBuffer + offset, data.data(), data.size()); +} + +void TeecSharedMemory::GetData(DataBuffer& data, size_t offset) const { + if (data.size() > (mMemory.size - offset)) { + throw common::TypeMismatchException("Not enough memory to get data: " + + std::to_string(data.size()) + + " requested, available " + + std::to_string(mMemory.size - offset) + + " at offset " + std::to_string(offset)); + } + + char* sharedBuffer = reinterpret_cast<char*>(mMemory.buffer); + memcpy(data.data(), sharedBuffer + offset, data.size()); +} + +TEEC_SharedMemory* TeecSharedMemory::GetMemoryPointer() { + return &mMemory; +} + +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecSharedMemory.h b/src/teec/TeecSharedMemory.h new file mode 100644 index 0000000..9af881c --- /dev/null +++ b/src/teec/TeecSharedMemory.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecSharedMemory class declaration + */ + +#ifndef LIBTEEC_TEEC_SHARED_MEMORY_H_ +#define LIBTEEC_TEEC_SHARED_MEMORY_H_ + +#include <memory> +#include <vector> +#include <tee_client_api.h> + +namespace extension { +namespace libteec { + +using DataBuffer = std::vector<uint8_t>; + +class TeecSharedMemory final +{ +public: + TeecSharedMemory(TEEC_Context* ctx, size_t size, uint32_t flags); + TeecSharedMemory(TEEC_Context* ctx, void* buffer, size_t size, uint32_t flags); + ~TeecSharedMemory(); + + void SetData(const DataBuffer& data, size_t offset); + void GetData(DataBuffer& data, size_t offset) const; + + TEEC_SharedMemory* GetMemoryPointer(); +private: + TEEC_SharedMemory mMemory; +}; + +using TeecSharedMemoryPtr = std::shared_ptr<TeecSharedMemory>; + +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_SHARED_MEMORY_H_
\ No newline at end of file diff --git a/src/teec/TeecTempMemoryAllocator.cc b/src/teec/TeecTempMemoryAllocator.cc new file mode 100644 index 0000000..65f8929 --- /dev/null +++ b/src/teec/TeecTempMemoryAllocator.cc @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecTempMemoryAllocator class definition + */ + +#include "TeecTempMemoryAllocator.h" + + +namespace extension { +namespace libteec { + +void* TeecTempMemoryAllocator::AllocateTempMemory(const picojson::array& array) { + mMemories.emplace_back(array.size()); + TempMemoryBuffer& memory = mMemories.back(); + + for (size_t i = 0; i < array.size(); ++i) + memory[i] = static_cast<uint8_t>(array[i].get<double>()); + + return memory.data(); +} + +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecTempMemoryAllocator.h b/src/teec/TeecTempMemoryAllocator.h new file mode 100644 index 0000000..84523b4 --- /dev/null +++ b/src/teec/TeecTempMemoryAllocator.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief TeecTempMemoryAllocator class declaration + */ + +#ifndef LIBTEEC_TEEC_TEMP_MEMORY_ALLOCATOR_H_ +#define LIBTEEC_TEEC_TEMP_MEMORY_ALLOCATOR_H_ + +#include <vector> +#include <list> +#include <common/picojson.h> + + +namespace extension { +namespace libteec { + +using TempMemoryBuffer = std::vector<uint8_t>; +using TempMemoryList = std::list<TempMemoryBuffer>; + +// An object used during OpenSession and InvokeCommand calls +// It's purpose is to temporarily allocate buffers on C++ side +// and keep them in memory until above calls end +class TeecTempMemoryAllocator final +{ +public: + // returns pointer for temp memory + void* AllocateTempMemory(const picojson::array& array); + +private: + TempMemoryList mMemories; +}; + +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_TEMP_MEMORY_ALLOCATOR_H_
\ No newline at end of file diff --git a/src/teec/TeecTranslations.cc b/src/teec/TeecTranslations.cc new file mode 100644 index 0000000..e6316cb --- /dev/null +++ b/src/teec/TeecTranslations.cc @@ -0,0 +1,379 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Teec to/from JSON translation function definitions + */ + +#include "TeecTranslations.h" +#include "TeecManager.h" +#include "TeecContext.h" +#include "TeecSharedMemory.h" +#include <tee_client_api.h> + +#define CASE_RESULT_TO_STRING(x) case x: return #x + +namespace { + +// JSON TEEC_Parameter parsing tokens +const std::string PARAM_TYPE_KEY = "type"; +const std::string PARAM_TYPE_NONE = "NONE"; +const std::string PARAM_TYPE_VALUE = "VALUE"; +const std::string PARAM_TYPE_MEMREF = "MEMREF"; +const std::string PARAM_TYPE_TMPREF = "TMPREF"; +const std::string PARAM_FLAG_KEY = "flag"; +const std::string PARAM_FLAG_NONE = "NONE"; +const std::string PARAM_FLAG_INPUT = "INPUT"; +const std::string PARAM_FLAG_OUTPUT = "OUTPUT"; +const std::string PARAM_FLAG_INOUT = "INOUT"; +const std::string PARAM_FLAG_WHOLE = "WHOLE"; +const std::string PARAM_FLAG_PARTIAL_INPUT = "PARTIAL_INPUT"; +const std::string PARAM_FLAG_PARTIAL_OUTPUT = "PARTIAL_OUTPUT"; +const std::string PARAM_FLAG_PARTIAL_INOUT = "PARTIAL_INOUT"; +const std::string PARAM_VALUE_A = "a"; +const std::string PARAM_VALUE_B = "a"; +const std::string PARAM_MEMREF_SIZE = "size"; +const std::string PARAM_MEMREF_OFFSET = "offset"; +const std::string PARAM_MEMREF_SHM = "shm"; +const std::string PARAM_TMPREF_MEM = "mem"; + +const uint32_t TEEC_OPERATION_COUNT = 4; + +} // namespace + +namespace extension { +namespace libteec { +namespace translations { + +std::string TeecResultToString(TEEC_Result result) { + switch (result) { + CASE_RESULT_TO_STRING(TEEC_SUCCESS); + CASE_RESULT_TO_STRING(TEEC_ERROR_GENERIC); + CASE_RESULT_TO_STRING(TEEC_ERROR_ACCESS_DENIED); + CASE_RESULT_TO_STRING(TEEC_ERROR_CANCEL); + CASE_RESULT_TO_STRING(TEEC_ERROR_ACCESS_CONFLICT); + CASE_RESULT_TO_STRING(TEEC_ERROR_EXCESS_DATA); + CASE_RESULT_TO_STRING(TEEC_ERROR_BAD_FORMAT); + CASE_RESULT_TO_STRING(TEEC_ERROR_BAD_PARAMETERS); + CASE_RESULT_TO_STRING(TEEC_ERROR_BAD_STATE); + CASE_RESULT_TO_STRING(TEEC_ERROR_ITEM_NOT_FOUND); + CASE_RESULT_TO_STRING(TEEC_ERROR_NOT_IMPLEMENTED); + CASE_RESULT_TO_STRING(TEEC_ERROR_NOT_SUPPORTED); + CASE_RESULT_TO_STRING(TEEC_ERROR_NO_DATA); + CASE_RESULT_TO_STRING(TEEC_ERROR_OUT_OF_MEMORY); + CASE_RESULT_TO_STRING(TEEC_ERROR_BUSY); + CASE_RESULT_TO_STRING(TEEC_ERROR_COMMUNICATION); + CASE_RESULT_TO_STRING(TEEC_ERROR_SECURITY); + CASE_RESULT_TO_STRING(TEEC_ERROR_SHORT_BUFFER); + CASE_RESULT_TO_STRING(TEEC_ERROR_EXTERNAL_CANCEL); + CASE_RESULT_TO_STRING(TEEC_ERROR_TARGET_DEAD); + // not throwing here, there are TEE internal error not known from + // TEEC header, moreover this function is usually used in throws anyway + default: return "TEEC_ERROR_UNKNOWN"; + } +} + +uint32_t StringToTeecLoginMethod(const std::string& str) { + if (str == "PUBLIC") return TEEC_LOGIN_PUBLIC; + if (str == "USER") return TEEC_LOGIN_USER; + if (str == "GROUP") return TEEC_LOGIN_GROUP; + if (str == "APPLICATION") return TEEC_LOGIN_APPLICATION; + throw common::InvalidValuesException("Invalid login type: " + str); +} + +uint32_t ParamTypeFromJSON(const picojson::object& obj) { + auto typeVal = obj.find(PARAM_TYPE_KEY); + if (typeVal == obj.end()) { + throw common::InvalidValuesException("Missing parameter type info"); + } + + auto flagVal = obj.find(PARAM_FLAG_KEY); + if (flagVal == obj.end()) { + throw common::InvalidValuesException("Flag parameter not added to operation"); + } + + const std::string& typeStr = typeVal->second.get<std::string>(); + const std::string& flagStr = flagVal->second.get<std::string>(); + + if (typeStr == PARAM_TYPE_VALUE) { + if (flagStr == PARAM_FLAG_INPUT) { + return TEEC_VALUE_INPUT; + } else if (flagStr == PARAM_FLAG_OUTPUT) { + return TEEC_VALUE_OUTPUT; + } else if (flagStr == PARAM_FLAG_INOUT) { + return TEEC_VALUE_INOUT; + } else { + throw common::InvalidValuesException("Invalid parameter flag info: " + + flagStr); + } + } else if (typeStr == PARAM_TYPE_MEMREF) { + if (flagStr == PARAM_FLAG_WHOLE) { + return TEEC_MEMREF_WHOLE; + } else if (flagStr == PARAM_FLAG_PARTIAL_INPUT) { + return TEEC_MEMREF_PARTIAL_INPUT; + } else if (flagStr == PARAM_FLAG_PARTIAL_OUTPUT) { + return TEEC_MEMREF_PARTIAL_OUTPUT; + } else if (flagStr == PARAM_FLAG_PARTIAL_INOUT) { + return TEEC_MEMREF_PARTIAL_INOUT; + } else { + throw common::InvalidValuesException("Invalid parameter flag info: " + + flagStr); + } + } else if (typeStr == PARAM_TYPE_TMPREF) { + if (flagStr == PARAM_FLAG_INPUT) { + return TEEC_MEMREF_TEMP_INPUT; + } else if (flagStr == PARAM_FLAG_OUTPUT) { + return TEEC_MEMREF_TEMP_OUTPUT; + } else if (flagStr == PARAM_FLAG_INOUT) { + return TEEC_MEMREF_TEMP_INOUT; + } else { + throw common::InvalidValuesException("Invalid parameter flag info: " + + flagStr); + } + } + + throw common::InvalidValuesException("Invalid parameter type info: " + + typeVal->second.get<std::string>()); +} + +TEEC_SharedMemory* SharedMemoryFromJSON(const picojson::object& object) { + auto cID = object.find("contextId"); + auto mID = object.find("memId"); + + if (cID == object.end() || mID == object.end()) { + throw common::InvalidValuesException("Invalid shared memory object provided as param"); + } + + const std::string& contextId = cID->second.get<std::string>(); + const std::string& memId = mID->second.get<std::string>(); + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + TeecSharedMemoryPtr mem = context->GetSharedMemory(memId); + return mem->GetMemoryPointer(); +} + +TEEC_Operation OperationFromJSON(const picojson::value& value, TeecTempMemoryAllocator& allocator) { + TEEC_Operation result; + result.started = 0; + result.paramTypes = 0; + + if (!value.is<picojson::array>()) { + return result; + } + + std::vector<uint32_t> paramTypes(TEEC_OPERATION_COUNT); + for (auto& p: paramTypes) { + p = TEEC_NONE; + } + + const picojson::array& array = value.get<picojson::array>(); + if (array.size() > TEEC_OPERATION_COUNT) { + throw common::InvalidValuesException("Too many operation parameters"); + } + + for (uint32_t i = 0; i < array.size(); ++i) { + const picojson::object& paramObject = array[i].get<picojson::object>(); + + auto type = paramObject.find(PARAM_TYPE_KEY); + if (type != paramObject.end()) { + paramTypes[i] = ParamTypeFromJSON(paramObject); + const std::string& paramTypeStr = type->second.get<std::string>(); + if (paramTypeStr == PARAM_TYPE_VALUE) { + auto valA = paramObject.find(PARAM_VALUE_A); + auto valB = paramObject.find(PARAM_VALUE_B); + if (valA != paramObject.end() && valB != paramObject.end()) { + result.params[i].value.a = static_cast<uint32_t>(valA->second.get<double>()); + result.params[i].value.b = static_cast<uint32_t>(valB->second.get<double>()); + } + } else if (paramTypeStr == PARAM_TYPE_MEMREF) { + auto size = paramObject.find(PARAM_MEMREF_SIZE); + auto offset = paramObject.find(PARAM_MEMREF_OFFSET); + auto shm = paramObject.find(PARAM_MEMREF_SHM); + if (size != paramObject.end() && + offset != paramObject.end() && + shm != paramObject.end()) { + result.params[i].memref.size = static_cast<size_t>(size->second.get<double>()); + result.params[i].memref.offset = static_cast<size_t>(offset->second.get<double>()); + result.params[i].memref.parent = SharedMemoryFromJSON(shm->second.get<picojson::object>()); + } + } else if (paramTypeStr == PARAM_TYPE_TMPREF) { + auto mem = paramObject.find(PARAM_TMPREF_MEM); + if (mem != paramObject.end()) { + const picojson::array& tmpMem = mem->second.get<picojson::array>(); + result.params[i].tmpref.size = tmpMem.size(); + result.params[i].tmpref.buffer = allocator.AllocateTempMemory(tmpMem); + } + } else { + throw common::InvalidValuesException("Invalid parameter type provided: " + + type->second.get<std::string>()); + } + } + } + + result.paramTypes = TEEC_PARAM_TYPES(paramTypes[0], paramTypes[1], paramTypes[2], paramTypes[3]); + return result; +} + +uint32_t SharedMemoryFlagsFromJSON(const picojson::value& value) { + if (!value.is<std::string>()) { + throw common::InvalidValuesException("Attempted to acquire shared memory flag from non-string object"); + } + + const std::string& flagStr = value.get<std::string>(); + if (flagStr == PARAM_FLAG_INPUT) { + return TEEC_MEM_INPUT; + } else if (flagStr == PARAM_FLAG_OUTPUT) { + return TEEC_MEM_OUTPUT; + } else if (flagStr == PARAM_FLAG_INOUT) { + return TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + } + + throw common::InvalidValuesException("Invalid flag provided: " + flagStr); +} + +DataBuffer DataBufferFromJSON(const picojson::value& value) { + if (!value.is<picojson::array>()) { + throw common::InvalidValuesException("Attempted to acquire data array from non-array object"); + } + + const picojson::array& array = value.get<picojson::array>(); + DataBuffer buffer(array.size()); + + for (size_t i = 0; i < array.size(); ++i) { + buffer[i] = static_cast<uint8_t>(array[i].get<double>()); + } + + return buffer; +} + +std::string JSONFromParamType(uint32_t paramType) { + switch (paramType) { + case TEEC_NONE: + return PARAM_TYPE_NONE; + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + return PARAM_TYPE_VALUE; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + return PARAM_TYPE_TMPREF; + case TEEC_MEMREF_WHOLE: + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + return PARAM_TYPE_MEMREF; + default: + throw common::InvalidValuesException("Unknown TEEC parameter type: " + std::to_string(paramType)); + }; +} + +std::string JSONFromParamFlag(uint32_t paramType) { + switch (paramType) { + case TEEC_NONE: + return PARAM_FLAG_NONE; + case TEEC_VALUE_INPUT: + case TEEC_MEMREF_TEMP_INPUT: + return PARAM_FLAG_INPUT; + case TEEC_VALUE_OUTPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + return PARAM_FLAG_OUTPUT; + case TEEC_VALUE_INOUT: + case TEEC_MEMREF_TEMP_INOUT: + return PARAM_FLAG_INOUT; + case TEEC_MEMREF_WHOLE: + return PARAM_FLAG_WHOLE; + case TEEC_MEMREF_PARTIAL_INPUT: + return PARAM_FLAG_PARTIAL_INPUT; + case TEEC_MEMREF_PARTIAL_OUTPUT: + return PARAM_FLAG_PARTIAL_OUTPUT; + case TEEC_MEMREF_PARTIAL_INOUT: + return PARAM_FLAG_PARTIAL_INOUT; + default: + throw common::InvalidValuesException("Unknown TEEC parameter type: " + std::to_string(paramType)); + }; +} + +picojson::value UpdateJSONParams(const picojson::value& json, TEEC_Operation op) { + const picojson::array& inParamArray = json.get<picojson::array>(); + picojson::array outParamArray; + + uint32_t paramTypes[4] = { + TEEC_PARAM_TYPE_GET(op.paramTypes, 0), + TEEC_PARAM_TYPE_GET(op.paramTypes, 1), + TEEC_PARAM_TYPE_GET(op.paramTypes, 2), + TEEC_PARAM_TYPE_GET(op.paramTypes, 3), + }; + + for (uint32_t i = 0; i < 4; ++i) { + picojson::object param; + + std::string paramTypeStr = JSONFromParamType(paramTypes[i]); + param.insert(std::make_pair( + PARAM_TYPE_KEY, picojson::value(paramTypeStr))); + param.insert(std::make_pair( + PARAM_FLAG_KEY, picojson::value(JSONFromParamFlag(paramTypes[i])))); + + if (paramTypeStr == PARAM_TYPE_VALUE) { + // value type can be completely overwritten + param.insert(std::make_pair(PARAM_VALUE_A, + picojson::value(static_cast<double>(op.params[i].value.a)))); + param.insert(std::make_pair(PARAM_VALUE_B, + picojson::value(static_cast<double>(op.params[i].value.b)))); + } else if (paramTypeStr == PARAM_TYPE_MEMREF) { + const picojson::object& memref = inParamArray[i].get<picojson::object>(); + auto shm = memref.find("shm"); + if (shm == memref.end()) { + throw common::InvalidValuesException("Invalid shm object"); + } + + // memref type copies shm from source, rest parameters from TA + param.insert(std::make_pair(PARAM_MEMREF_SIZE, + picojson::value(static_cast<double>(op.params[i].memref.size)))); + param.insert(std::make_pair(PARAM_MEMREF_OFFSET, + picojson::value(static_cast<double>(op.params[i].memref.offset)))); + param.insert(std::make_pair(PARAM_MEMREF_SHM, shm->second)); + } else if (paramTypeStr == PARAM_TYPE_TMPREF) { + picojson::array buf(op.params[i].tmpref.size); + uint8_t* opBuf = reinterpret_cast<uint8_t*>(op.params[i].tmpref.buffer); + for (size_t i = 0; i < buf.size(); ++i) + buf[i] = picojson::value(static_cast<double>(opBuf[i])); + + param.insert(std::make_pair(PARAM_TMPREF_MEM, picojson::value(buf))); + } else if (paramTypeStr != PARAM_TYPE_NONE) { + throw common::InvalidValuesException( + "Invalid parameter type read from operation: " + paramTypeStr); + } + + outParamArray.push_back(picojson::value(param)); + } + + return picojson::value(outParamArray); +} + +picojson::value JSONFromDataBuffer(const DataBuffer& buffer) { + picojson::array result(buffer.size()); + + for (uint32_t i = 0; i < buffer.size(); ++i) { + result[i] = picojson::value(static_cast<double>(buffer[i])); + } + + return picojson::value(result); +} + +} // namespace translations +} // namespace libteec +} // namespace extension diff --git a/src/teec/TeecTranslations.h b/src/teec/TeecTranslations.h new file mode 100644 index 0000000..c8b3b3b --- /dev/null +++ b/src/teec/TeecTranslations.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2017 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 + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Teec to/from JSON translation function declarations + */ + +#ifndef LIBTEEC_TEEC_TRANSLATIONS_H_ +#define LIBTEEC_TEEC_TRANSLATIONS_H_ + +#include "TeecSharedMemory.h" + +#include "TeecTempMemoryAllocator.h" + +#include <tee_client_api.h> +#include <string> + +#include <common/picojson.h> +#include <common/platform_exception.h> + + +namespace extension { +namespace libteec { +namespace translations { + +std::string TeecResultToString(TEEC_Result result); +uint32_t StringToTeecLoginMethod(const std::string& str); +TEEC_Operation OperationFromJSON(const picojson::value& value, TeecTempMemoryAllocator& allocator); +DataBuffer DataBufferFromJSON(const picojson::value& value); +uint32_t SharedMemoryFlagsFromJSON(const picojson::value& value); +picojson::value UpdateJSONParams(const picojson::value& json, TEEC_Operation op); +picojson::value JSONFromDataBuffer(const DataBuffer& buffer); + +} // namespace translations +} // namespace libteec +} // namespace extension + +#endif // LIBTEEC_TEEC_TRANSLATIONS_H_ diff --git a/src/teec/libteec_api.js b/src/teec/libteec_api.js index 68811dd..92e3e04 100644 --- a/src/teec/libteec_api.js +++ b/src/teec/libteec_api.js @@ -28,7 +28,7 @@ function ListenerManager(native, listenerName, handle) { this.nativeSet = false; this.native = native; this.listenerName = listenerName; - this.handle = handle || function(msg, listener, watchId) {}; + this.handle = handle || function() {}; } ListenerManager.prototype.addListener = function(callback, nativeCall, data) { @@ -60,17 +60,13 @@ ListenerManager.prototype.removeListener = function(watchId, nativeCall) { } if (this.nativeSet && type_.isEmptyObject(this.listeners)) { - this.native.callSync(nativeCall); - this.native.removeListener(this.listenerName); - this.nativeSet = false; + this.native.callSync(nativeCall); + this.native.removeListener(this.listenerName); + this.nativeSet = false; } }; -function SetReadOnlyProperty(obj, n, v) { - Object.defineProperty(obj, n, {value: v, writable: false}); -} - var TeecLoginMethod = { PUBLIC: 'PUBLIC', USER: 'USER', @@ -98,15 +94,21 @@ var TeecSharedMemoryFlags = { OUTPUT: 'OUTPUT', INOUT: 'INOUT' }; +var TEEC_MAX_OPERATION_LENGTH = 4; +var TEEC_PARAMETER_TYPE_VALUE = 'VALUE'; +var TEEC_PARAMETER_TYPE_MEMREF = 'MEMREF'; +var TEEC_PARAMETER_TYPE_TMPREF = 'TMPREF'; -function LibTeecManager() { - // constructor of LibTeecManager - +function TeecParameter() { } -LibTeecManager.prototype.getContext = function(name) { + +function LibTeecManager() { +} + +LibTeecManager.prototype.getContext = function() { var args = validator_.validateArgs(arguments, [ {name: 'name', type: types_.STRING, optional: true, nullable: true} ]); @@ -115,58 +117,149 @@ LibTeecManager.prototype.getContext = function(name) { name: args.name }; - var result = native_.callSync('LibTeecManager_getContext', data); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } + return new TeecContext(native_.getResultObject(result)); +}; + + +function TeecSession(contextId, sessionId) { + this.contextId = contextId; + this.sessionId = sessionId; +} + +TeecSession.prototype.close = function() { + var data = { + contextId: this.contextId, + sessionId: this.sessionId + }; + + var result = native_.callSync('TeecSession_close', data); + + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } }; +TeecSession.prototype.invokeCommand = + function(cmd, params, successCallback, errorCallback) { + var args = validator_.validateArgs(arguments, [ + {name: 'cmd', type: types_.LONG}, + {name: 'params', type: types_.ARRAY, values: TeecParameter, + nullable: true}, + {name: 'successCallback', type: types_.FUNCTION}, + {name: 'errorCallback', type: types_.FUNCTION, optional: true, + nullable: true} + ]); + if (params.length > TEEC_MAX_OPERATION_LENGTH) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, + 'Input array params has too high length'); + } -function TeecContext() { - // constructor of TeecContext + var data = { + contextId: this.contextId, + sessionId: this.sessionId, + cmd: args.cmd, + params: args.params, + successCallback: args.successCallback, + errorCallback: args.errorCallback + }; -} + var callback = function(result) { + if (native_.isFailure(result)) { + native_.callIfPossible(args.errorCallback, + native_.getErrorObject(result)); + return; + } + + var retArgs = native_.getResultObject(result); + + // update parameters after call + // to avoid losing TeecSharedMemory's functions, we copy MEMREF + // attributes via a function, instead of a typical substitution + for (var i = 0; i < params.length; ++i) { + switch (params[i].type) { + case TEEC_PARAMETER_TYPE_VALUE: + params[i] = retArgs.params[i]; + break; + case TEEC_PARAMETER_TYPE_MEMREF: + params[i].copyParams(retArgs.params[i]); + break; + case TEEC_PARAMETER_TYPE_TMPREF: + params[i] = retArgs.params[i]; + break; + default: + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, + 'Received incorrect param object from plugin'); + }; + } + native_.callIfPossible(args.successCallback, retArgs.cmd, params); + }; + + var result = native_.call('TeecSession_invokeCommand', data, callback); -TeecContext.prototype.openSession = function(taUUID, loginMethod, connectionData, params, successCallback, errorCallback) { + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + + return native_.getResultObject(result); +}; + + + +function TeecContext(id) { + // constructor of TeecContext + this.contextId = id; +} + +TeecContext.prototype.openSession = + function(taUUID, loginMethod, connectionData, params, successCallback, + errorCallback) { var args = validator_.validateArgs(arguments, [ {name: 'taUUID', type: types_.STRING}, - {name: 'loginMethod', type: types_.ENUM, values: ['PUBLIC', 'USER', 'GROUP', 'APPLICATION']}, - {name: 'connectionData', type: types_.BYTE}, - {name: 'params', type: types_.PLATFORM_OBJECT, values: tizen.TeecParameter}, + {name: 'loginMethod', type: types_.ENUM, + values: ['PUBLIC', 'USER', 'GROUP', 'APPLICATION']}, + {name: 'connectionData', type: types_.UNSIGNED_LONG, nullable: true}, + {name: 'params', type: types_.ARRAY, values: TeecParameter, + nullable: true}, {name: 'successCallback', type: types_.FUNCTION}, - {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true} + {name: 'errorCallback', type: types_.FUNCTION, optional: true, + nullable: true} ]); var data = { + contextId: this.contextId, taUUID: args.taUUID, loginMethod: args.loginMethod, connectionData: args.connectionData, params: args.params }; - - - - - + var cId = this.contextId; var callback = function(result) { if (native_.isFailure(result)) { native_.callIfPossible(args.errorCallback, native_.getErrorObject(result)); return; } - native_.callIfPossible(args.successCallback); - }; - native_.call('TeecContext_openSession', data, callback); + var session = new TeecSession(cId, native_.getResultObject(result)); + native_.callIfPossible(args.successCallback, session); + }; + var result = native_.call('TeecContext_openSession', data, callback); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + return native_.getResultObject(result); }; TeecContext.prototype.revokeCommand = function(id) { @@ -178,13 +271,11 @@ TeecContext.prototype.revokeCommand = function(id) { id: args.id }; - var result = native_.callSync('TeecContext_revokeCommand', data); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - }; TeecContext.prototype.allocateSharedMemory = function(size, flags) { @@ -194,18 +285,18 @@ TeecContext.prototype.allocateSharedMemory = function(size, flags) { ]); var data = { + contextId: this.contextId, size: args.size, flags: args.flags }; - var result = native_.callSync('TeecContext_allocateSharedMemory', data); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - return new TeecSharedMemory(native_.getResultObject(result)); + return new TeecSharedMemory(this.contextId, native_.getResultObject(result)); }; TeecContext.prototype.registerSharedMemory = function(addr, size, flags) { @@ -221,14 +312,13 @@ TeecContext.prototype.registerSharedMemory = function(addr, size, flags) { flags: args.flags }; - var result = native_.callSync('TeecContext_registerSharedMemory', data); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - return new TeecSharedMemory(native_.getResultObject(result)); + return new TeecSharedMemory(this.contextId, native_.getResultObject(result)); }; TeecContext.prototype.releaseSharedMemory = function(shm) { @@ -237,88 +327,133 @@ TeecContext.prototype.releaseSharedMemory = function(shm) { ]); var data = { - shm: args.shm + contextId: this.contextId, + memId: args.shm.memId }; - var result = native_.callSync('TeecContext_releaseSharedMemory', data); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - }; -function TeecSharedMemory() { +function TeecSharedMemory(contextId, memId) { // constructor of TeecSharedMemory - - SetReadOnlyProperty(this, 'size', null); // read only property + this.contextId = contextId; + this.memId = memId; } - TeecSharedMemory.prototype.setData = function(data, offset) { var args = validator_.validateArgs(arguments, [ - {name: 'data', type: types_.BYTE}, - {name: 'offset', type: types_.LONG_LONG} + {name: 'data', type: types_.ARRAY, values: types_.BYTE }, + {name: 'offset', type: types_.LONG_LONG } ]); - var data = { + var packed = { + contextId: this.contextId, + memId: this.memId, data: args.data, offset: args.offset }; - - var result = native_.callSync('TeecSharedMemory_setData', data); + var result = native_.callSync('TeecSharedMemory_setData', packed); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - }; TeecSharedMemory.prototype.getData = function(data, offset) { var args = validator_.validateArgs(arguments, [ - {name: 'data', type: types_.BYTE}, + {name: 'data', type: types_.ARRAY, values: types_.BYTE }, {name: 'offset', type: types_.LONG_LONG} ]); - var data = { + var packed = { + contextId: this.contextId, + memId: this.memId, data: args.data, offset: args.offset }; - - var result = native_.callSync('TeecSharedMemory_getData', data); + var result = native_.callSync('TeecSharedMemory_getData', packed); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } + var out = native_.getResultObject(result); + for (var i = 0; i < data.length; ++i) + data[i] = out[i]; +}; + +TeecSharedMemory.prototype.copyParams = function(src) { + this.contextId = src.contextId; + this.memId = src.memId; }; -function TeecRegisteredMemory(memory, offset, size) { +function TeecValue(a, b, flag) { + // constructor of TeecValue + validator_.isConstructorCall(this, TeecValue); + var args = validator_.validateArgs(arguments, [ + {name: 'a', type: types_.UNSIGNED_LONG}, + {name: 'b', type: types_.UNSIGNED_LONG}, + {name: 'flag', type: types_.ENUM, values: ['INPUT', 'OUTPUT', 'INOUT']} + ]); + + this.type = TEEC_PARAMETER_TYPE_VALUE; + this.flag = args.flag; + this.a = args.a; + this.b = args.b; +} + +TeecValue.prototype = new TeecParameter(); +TeecValue.prototype.constructor = TeecValue; + +function TeecRegisteredMemory(memory, offset, size, flag) { // constructor of TeecRegisteredMemory validator_.isConstructorCall(this, TeecRegisteredMemory); + var args = validator_.validateArgs(arguments, [ + {name: 'memory', type: types_.PLATFORM_OBJECT, values: TeecSharedMemory }, + {name: 'offset', type: types_.UNSIGNED_LONG_LONG }, + {name: 'size', type: types_.UNSIGNED_LONG_LONG }, + {name: 'flag', type: types_.ENUM, values: ['WHOLE', 'PARTIAL_INPUT', 'PARTIAL_OUTPUT', 'PARTIAL_INOUT']} + ]); - this.shm = null; - this.offset = offset; - this.size = memory.size; + this.type = TEEC_PARAMETER_TYPE_MEMREF; + this.flag = args.flag; + this.shm = memory; + this.size = args.size; + this.offset = args.offset; } TeecRegisteredMemory.prototype = new TeecParameter(); TeecRegisteredMemory.prototype.constructor = TeecRegisteredMemory; +TeecRegisteredMemory.prototype.copyParams = function(src) { + this.type = src.type; + this.flag = src.flag; + this.size = src.size; + this.offset = src.offset; + this.shm.copyParams(src.shm); +}; - -function TeecTempMemory(mem) { +function TeecTempMemory(mem, flag) { // constructor of TeecTempMemory validator_.isConstructorCall(this, TeecTempMemory); + var args = validator_.validateArgs(arguments, [ + {name: 'mem', type: types_.ARRAY, values: types_.BYTE }, + {name: 'flag', type: types_.ENUM, values: ['INPUT', 'OUTPUT', 'INOUT']} + ]); - this.mem = mem; + this.type = TEEC_PARAMETER_TYPE_TMPREF; + this.mem = args.mem; + this.flag = args.flag; } TeecTempMemory.prototype = new TeecParameter(); @@ -326,23 +461,7 @@ TeecTempMemory.prototype.constructor = TeecTempMemory; -function TeecValue(a, b) { - // constructor of TeecValue - validator_.isConstructorCall(this, TeecValue); - - this.a = a; - this.b = b; -} - -TeecValue.prototype = new TeecParameter(); -TeecValue.prototype.constructor = TeecValue; - - - exports = new LibTeecManager(); -tizen.TeecContext = TeecContext; -tizen.TeecSharedMemory = TeecSharedMemory; tizen.TeecRegisteredMemory = TeecRegisteredMemory; tizen.TeecTempMemory = TeecTempMemory; tizen.TeecValue = TeecValue; - diff --git a/src/teec/libteec_extension.cc b/src/teec/libteec_extension.cc index 48953b1..1d48506 100644 --- a/src/teec/libteec_extension.cc +++ b/src/teec/libteec_extension.cc @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Libteec extension definitions + */ #include "teec/libteec_extension.h" diff --git a/src/teec/libteec_extension.h b/src/teec/libteec_extension.h index 52188a9..f1f94b3 100644 --- a/src/teec/libteec_extension.h +++ b/src/teec/libteec_extension.h @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Libteec extension declaration + */ #ifndef LIBTEEC_LIBTEEC_EXTENSION_H_ #define LIBTEEC_LIBTEEC_EXTENSION_H_ diff --git a/src/teec/libteec_instance.cc b/src/teec/libteec_instance.cc index 5ac689c..6cbfbbb 100644 --- a/src/teec/libteec_instance.cc +++ b/src/teec/libteec_instance.cc @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +/** + * Copyright (c) 2017 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. @@ -13,24 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Libteec instance definitions + */ -#include "teec/libteec_instance.h" +#include "libteec_instance.h" +#include "TeecManager.h" +#include "TeecContext.h" +#include "TeecTranslations.h" +#include "TeecTempMemoryAllocator.h" #include <functional> -#include "common/picojson.h" -#include "common/logger.h" -#include "common/platform_exception.h" +#include <common/picojson.h> +#include <common/logger.h> +#include <common/platform_exception.h> +#include <common/task-queue.h> +#include <common/converter.h> +#include <common/tools.h> -namespace extension { -namespace libteec { namespace { -// The privileges that required in Libteec API -const std::string kPrivilegeLibteec = ""; + +// The privilege required in Libteec API +const std::string kPrivilegeLibteec = "http://tizen.org/privilege/tee.client"; } // namespace +namespace extension { +namespace libteec { + using namespace common; using namespace extension::libteec; @@ -39,79 +53,20 @@ LibteecInstance::LibteecInstance() { #define REGISTER_SYNC(c,x) \ RegisterSyncHandler(c, std::bind(&LibteecInstance::x, this, _1, _2)); REGISTER_SYNC("LibTeecManager_getContext", LibTeecManagerGetContext); + REGISTER_SYNC("TeecSharedMemory_getData", TeecSharedMemoryGetData); REGISTER_SYNC("TeecSharedMemory_setData", TeecSharedMemorySetData); REGISTER_SYNC("TeecContext_releaseSharedMemory", TeecContextReleaseSharedMemory); - REGISTER_SYNC("TeecContext_openSession", TeecContextOpenSession); REGISTER_SYNC("TeecContext_registerSharedMemory", TeecContextRegisterSharedMemory); REGISTER_SYNC("TeecContext_allocateSharedMemory", TeecContextAllocateSharedMemory); - REGISTER_SYNC("TeecSharedMemory_getData", TeecSharedMemoryGetData); REGISTER_SYNC("TeecContext_revokeCommand", TeecContextRevokeCommand); + REGISTER_SYNC("TeecSession_close", TeecSessionClose); #undef REGISTER_SYNC -} - -LibteecInstance::~LibteecInstance() { -} - - -enum LibteecCallbacks { - LibTeecManagerGetContextCallback, - TeecSharedMemorySetDataCallback, - TeecContextReleaseSharedMemoryCallback, - TeecContextOpenSessionCallback, - TeecContextRegisterSharedMemoryCallback, - TeecContextAllocateSharedMemoryCallback, - TeecSharedMemoryGetDataCallback, - TeecContextRevokeCommandCallback -}; - -static void ReplyAsync(LibteecInstance* instance, LibteecCallbacks cbfunc, - int callbackId, bool isSuccess, picojson::object& param) { - param["callbackId"] = picojson::value(static_cast<double>(callbackId)); - param["status"] = picojson::value(isSuccess ? "success" : "error"); - - // insert result for async callback to param - switch(cbfunc) { - case LibTeecManagerGetContextCallback: { - // do something... - break; - } - case TeecContextOpenSessionCallback: { - // do something... - break; - } - case TeecContextRevokeCommandCallback: { - // do something... - break; - } - case TeecContextAllocateSharedMemoryCallback: { - // do something... - break; - } - case TeecContextRegisterSharedMemoryCallback: { - // do something... - break; - } - case TeecContextReleaseSharedMemoryCallback: { - // do something... - break; - } - case TeecSharedMemorySetDataCallback: { - // do something... - break; - } - case TeecSharedMemoryGetDataCallback: { - // do something... - break; - } - default: { - LoggerE("Invalid Callback Type"); - return; - } - } - - picojson::value result = picojson::value(param); - instance->PostMessage(result.serialize().c_str()); + #define REGISTER_ASYNC(c,x) \ + RegisterSyncHandler(c, std::bind(&LibteecInstance::x, this, _1, _2)); + REGISTER_ASYNC("TeecContext_openSession", TeecContextOpenSession); + REGISTER_ASYNC("TeecSession_invokeCommand", TeecSessionInvokeCommand); + #undef REGISTER_ASYNC } #define CHECK_EXIST(args, name, out) \ @@ -120,116 +75,270 @@ static void ReplyAsync(LibteecInstance* instance, LibteecCallbacks cbfunc, return;\ } +void LibteecInstance::LibTeecManagerGetContext(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); -void LibteecInstance::LibTeecManagerGetContext(const picojson::value& args, picojson::object& out) { - - const std::string& name = args.get("name").get<std::string>(); - - // implement it + const picojson::value& name = args.get("name"); + std::string contextName; + if (name.is<std::string>()) { + contextName = name.get<std::string>(); + } - // if success - // ReportSuccess(out); - // if error - // ReportError(out); + try { + TeecManager::Instance().GetContext(contextName); + ReportSuccess(picojson::value(contextName), out); + } catch (const PlatformException& e) { + ReportError(e, out); + } } + void LibteecInstance::TeecContextOpenSession(const picojson::value& args, picojson::object& out) { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); CHECK_EXIST(args, "callbackId", out) - CHECK_EXIST(args, "connectionData", out) - - int callbackId = static_cast<int>(args.get("callbackId").get<double>()); - int connectionData = args.get("connectionData").get<int>(); - - // implement it + CHECK_EXIST(args, "contextId", out) + CHECK_EXIST(args, "taUUID", out) + CHECK_EXIST(args, "loginMethod", out) + + double callbackId = args.get("callbackId").get<double>(); + std::string contextId = args.get("contextId").get<std::string>(); + std::string uuid = args.get("taUUID").get<std::string>(); + const uint32_t loginMethod = translations::StringToTeecLoginMethod(args.get("loginMethod").get<std::string>()); + + TeecContextPtr context; + uint32_t connectionData = 0; + uint32_t* connectionDataPtr = nullptr; + uint32_t opId = 0; + + try { + context = TeecManager::Instance().GetContext(contextId); + + if (args.get("connectionData").is<double>()) { + connectionData = static_cast<uint32_t>(args.get("connectionData").get<double>()); + connectionDataPtr = &connectionData; + } - // call ReplyAsync in later (Asynchronously) + opId = TeecManager::Instance().CreateOperation(); + } catch (const PlatformException& e) { + ReportError(e, out); + } - // if success - // ReportSuccess(out); - // if error - // ReportError(out); -} -void LibteecInstance::TeecContextRevokeCommand(const picojson::value& args, picojson::object& out) { + auto openSession = [=](const std::shared_ptr<picojson::value>& response) -> void { + try { + TeecTempMemoryAllocator allocator; + + TEEC_Operation op = TeecManager::Instance().GetOperation(opId); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); + if (args.get("params").is<picojson::array>()) { + op = translations::OperationFromJSON(args.get("params"), allocator); + } + + std::string sid = context->OpenSession(uuid, loginMethod, connectionDataPtr, &op, nullptr); + TeecManager::Instance().RemoveOperation(opId); + ReportSuccess(picojson::value(sid), response->get<picojson::object>()); + } catch (const PlatformException& e) { + ReportError(e, response->get<picojson::object>()); + } + }; + auto openSessionResponse = + [callbackId, this](const std::shared_ptr<picojson::value>& response) -> void { + picojson::object& obj = response->get<picojson::object>(); + obj.insert(std::make_pair("callbackId", picojson::value(callbackId))); + Instance::PostMessage(this, response->serialize().c_str()); + }; - // implement it + auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object())); + TaskQueue::GetInstance().Queue<picojson::value>(openSession, openSessionResponse, data); - // if success - // ReportSuccess(out); - // if error - // ReportError(out); + ReportSuccess(picojson::value(static_cast<double>(opId)), out); } -void LibteecInstance::TeecContextAllocateSharedMemory(const picojson::value& args, picojson::object& out) { - CHECK_EXIST(args, "size", out) - - double size = args.get("size").get<double>(); - - // implement it - - // if success - // ReportSuccess(out); - // if error - // ReportError(out); +void LibteecInstance::TeecContextRevokeCommand(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "id", out); + + try { + uint32_t id = static_cast<uint32_t>(args.get("id").get<double>()); + TEEC_Operation op = TeecManager::Instance().GetOperation(id); + TEEC_RequestCancellation(&op); + ReportSuccess(out); + } catch (const PlatformException& e) { + ReportError(e, out); + } } -void LibteecInstance::TeecContextRegisterSharedMemory(const picojson::value& args, picojson::object& out) { - CHECK_EXIST(args, "addr", out) - CHECK_EXIST(args, "size", out) - - double addr = args.get("addr").get<double>(); - double size = args.get("size").get<double>(); - - // implement it +void LibteecInstance::TeecContextAllocateSharedMemory(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "contextId", out); + CHECK_EXIST(args, "size", out); + CHECK_EXIST(args, "flags", out); + + size_t size = static_cast<size_t>(args.get("size").get<double>()); + uint32_t flags = translations::SharedMemoryFlagsFromJSON(args.get("flags")); + std::string contextId = args.get("contextId").get<std::string>(); + + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + std::string memId = context->CreateSharedMemory(size, flags); + ReportSuccess(picojson::value(memId), out); + } catch (const PlatformException& e) { + ReportError(e, out); + } +} - // if success - // ReportSuccess(out); - // if error - // ReportError(out); +void LibteecInstance::TeecContextRegisterSharedMemory(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "contextId", out); + CHECK_EXIST(args, "buffer", out); + CHECK_EXIST(args, "size", out); + CHECK_EXIST(args, "flags", out); + + void* buffer = reinterpret_cast<void*>(static_cast<size_t>(args.get("buffer").get<double>())); + size_t size = static_cast<size_t>(args.get("size").get<double>()); + uint32_t flags = static_cast<uint32_t>(args.get("flags").get<double>()); + std::string contextId = args.get("contextId").get<std::string>(); + + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + std::string memId = context->CreateSharedMemory(buffer, size, flags); + ReportSuccess(picojson::value(memId), out); + } catch (const PlatformException& e) { + ReportError(e, out); + } } -void LibteecInstance::TeecContextReleaseSharedMemory(const picojson::value& args, picojson::object& out) { +void LibteecInstance::TeecContextReleaseSharedMemory(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "contextId", out); + CHECK_EXIST(args, "memId", out); - // implement it + std::string contextId = args.get("contextId").get<std::string>(); + std::string memId = args.get("memId").get<std::string>(); + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + context->ReleaseSharedMemory(memId); + } catch (const PlatformException& e) { + ReportError(e, out); + } +} - // if success - // ReportSuccess(out); - // if error - // ReportError(out); +void LibteecInstance::TeecSharedMemorySetData(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "data", out); + CHECK_EXIST(args, "offset", out); + + std::string contextId = args.get("contextId").get<std::string>(); + std::string memId = args.get("memId").get<std::string>(); + DataBuffer data = translations::DataBufferFromJSON(args.get("data")); + size_t offset = static_cast<size_t>(args.get("offset").get<double>()); + + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + TeecSharedMemoryPtr shmem = context->GetSharedMemory(memId); + shmem->SetData(data, offset); + ReportSuccess(out); + } catch (const PlatformException& e) { + ReportError(e, out); + } } -void LibteecInstance::TeecSharedMemorySetData(const picojson::value& args, picojson::object& out) { - CHECK_EXIST(args, "data", out) - CHECK_EXIST(args, "offset", out) - int data = args.get("data").get<int>(); - double offset = args.get("offset").get<double>(); +void LibteecInstance::TeecSharedMemoryGetData(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "data", out); + CHECK_EXIST(args, "offset", out); + + std::string contextId = args.get("contextId").get<std::string>(); + std::string memId = args.get("memId").get<std::string>(); + DataBuffer data = translations::DataBufferFromJSON(args.get("data")); + size_t offset = static_cast<size_t>(args.get("offset").get<double>()); + + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + TeecSharedMemoryPtr shmem = context->GetSharedMemory(memId); + shmem->GetData(data, offset); + ReportSuccess(translations::JSONFromDataBuffer(data), out); + } catch (const PlatformException& e) { + ReportError(e, out); + } +} - // implement it +void LibteecInstance::TeecSessionClose(const picojson::value& args, picojson::object& out) const { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "contextId", out); + CHECK_EXIST(args, "sessionId", out); + const std::string contextId = args.get("contextId").get<std::string>(); + const std::string sessionId = args.get("sessionId").get<std::string>(); - // if success - // ReportSuccess(out); - // if error - // ReportError(out); + try { + TeecContextPtr context = TeecManager::Instance().GetContext(contextId); + context->CloseSession(sessionId); + ReportSuccess(out); + } catch (const PlatformException& e) { + ReportError(e, out); + } } -void LibteecInstance::TeecSharedMemoryGetData(const picojson::value& args, picojson::object& out) { - CHECK_EXIST(args, "data", out) - CHECK_EXIST(args, "offset", out) - int data = args.get("data").get<int>(); - double offset = args.get("offset").get<double>(); +void LibteecInstance::TeecSessionInvokeCommand(const picojson::value& args, picojson::object& out) { + CHECK_PRIVILEGE_ACCESS(kPrivilegeLibteec, &out); + CHECK_EXIST(args, "callbackId", out); + CHECK_EXIST(args, "contextId", out); + CHECK_EXIST(args, "sessionId", out); + CHECK_EXIST(args, "cmd", out); + + const double callbackId = args.get("callbackId").get<double>(); + const std::string contextId = args.get("contextId").get<std::string>(); + const std::string sessionId = args.get("sessionId").get<std::string>(); + const uint32_t cmd = static_cast<uint32_t>(args.get("cmd").get<double>()); + + TeecContextPtr context; + TeecSessionPtr session; + uint32_t opId = 0; + + try { + context = TeecManager::Instance().GetContext(contextId); + session = context->GetSession(sessionId); + opId = TeecManager::Instance().CreateOperation(); + } catch (const PlatformException& e) { + ReportError(e, out); + } - // implement it + auto invoke = [=](const std::shared_ptr<picojson::value>& response) -> void { + try { + TeecTempMemoryAllocator allocator; + TEEC_Operation op = TeecManager::Instance().GetOperation(opId); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); + if (args.get("params").is<picojson::array>()) { + op = translations::OperationFromJSON(args.get("params"), allocator); + } + + session->InvokeCommand(cmd, &op, NULL); + TeecManager::Instance().RemoveOperation(opId); + + picojson::object result; + result.insert(std::make_pair("cmd", picojson::value(static_cast<double>(cmd)))); + result.insert(std::make_pair("params", translations::UpdateJSONParams(args.get("params"), op))); + ReportSuccess(picojson::value(result), response->get<picojson::object>()); + } catch (const PlatformException& e) { + ReportError(e, response->get<picojson::object>()); + } + }; + auto invokeResponse = + [callbackId, this](const std::shared_ptr<picojson::value>& response) -> void { + picojson::object& obj = response->get<picojson::object>(); + obj.insert(std::make_pair("callbackId", picojson::value(callbackId))); + Instance::PostMessage(this, response->serialize().c_str()); + }; - // if success - // ReportSuccess(out); - // if error - // ReportError(out); -} + auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object())); + TaskQueue::GetInstance().Queue<picojson::value>(invoke, invokeResponse, data); + ReportSuccess(picojson::value(static_cast<double>(opId)), out); +} #undef CHECK_EXIST diff --git a/src/teec/libteec_instance.h b/src/teec/libteec_instance.h index 48c7b7d..1e20757 100644 --- a/src/teec/libteec_instance.h +++ b/src/teec/libteec_instance.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2017 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. @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Libteec instance declaration + */ #ifndef LIBTEEC_LIBTEEC_INSTANCE_H_ #define LIBTEEC_LIBTEEC_INSTANCE_H_ @@ -25,17 +30,25 @@ namespace libteec { class LibteecInstance : public common::ParsedInstance { public: LibteecInstance(); - virtual ~LibteecInstance(); + virtual ~LibteecInstance() = default; private: - void LibTeecManagerGetContext(const picojson::value& args, picojson::object& out); - void TeecSharedMemorySetData(const picojson::value& args, picojson::object& out); - void TeecContextReleaseSharedMemory(const picojson::value& args, picojson::object& out); + void LibTeecManagerGetContext(const picojson::value& args, picojson::object& out) const; + + // SharedMemory + void TeecSharedMemorySetData(const picojson::value& args, picojson::object& out) const; + void TeecSharedMemoryGetData(const picojson::value& args, picojson::object& out) const; + + // Context + void TeecContextReleaseSharedMemory(const picojson::value& args, picojson::object& out) const; void TeecContextOpenSession(const picojson::value& args, picojson::object& out); - void TeecContextRegisterSharedMemory(const picojson::value& args, picojson::object& out); - void TeecContextAllocateSharedMemory(const picojson::value& args, picojson::object& out); - void TeecSharedMemoryGetData(const picojson::value& args, picojson::object& out); - void TeecContextRevokeCommand(const picojson::value& args, picojson::object& out); + void TeecContextRegisterSharedMemory(const picojson::value& args, picojson::object& out) const; + void TeecContextAllocateSharedMemory(const picojson::value& args, picojson::object& out) const; + void TeecContextRevokeCommand(const picojson::value& args, picojson::object& out) const; + + // Session + void TeecSessionClose(const picojson::value& args, picojson::object& out) const; + void TeecSessionInvokeCommand(const picojson::value& args, picojson::object& out); }; } // namespace libteec diff --git a/src/teec/teec.gyp b/src/teec/teec.gyp index a6ab469..3d2bb02 100644 --- a/src/teec/teec.gyp +++ b/src/teec/teec.gyp @@ -12,14 +12,28 @@ 'libteec_extension.h', 'libteec_instance.cc', 'libteec_instance.h', + 'TeecManager.cc', + 'TeecManager.h', + 'TeecTranslations.cc', + 'TeecTranslations.h', + 'TeecContext.cc', + 'TeecContext.h', + 'TeecSession.cc', + 'TeecSession.h', + 'TeecSharedMemory.cc', + 'TeecSharedMemory.h', + 'TeecTempMemoryAllocator.cc', + 'TeecTempMemoryAllocator.h' ], 'include_dirs': [ '../', '<(SHARED_INTERMEDIATE_DIR)', ], 'variables': { + 'pkg-config': 'pkg-config', 'packages': [ 'webapi-plugins', + 'tef-libteec', ], }, }, |