From 501d3a6ad44bc8cfe1c834e13be6533d0b702ecd Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 28 Nov 2014 23:18:13 +0100 Subject: [PATCH] Add cynara talker This patch introduces class for talking with cynara service. Change-Id: Ic04b65bbfdfac920f036eab17a90c47be2dec983 --- src/agent/CMakeLists.txt | 1 + src/agent/main/Agent.cpp | 20 ++++- src/agent/main/Agent.h | 11 ++- src/agent/main/CynaraTalker.cpp | 182 ++++++++++++++++++++++++++++++++++++++++ src/agent/main/CynaraTalker.h | 63 ++++++++++++++ 5 files changed, 271 insertions(+), 6 deletions(-) create mode 100644 src/agent/main/CynaraTalker.cpp create mode 100644 src/agent/main/CynaraTalker.h diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index 5d90013..8748112 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -26,6 +26,7 @@ SET(ASKUSER_AGENT_PATH ${ASKUSER_PATH}/agent) SET(ASKUSER_SOURCES ${ASKUSER_AGENT_PATH}/main/Agent.cpp + ${ASKUSER_AGENT_PATH}/main/CynaraTalker.cpp ${ASKUSER_AGENT_PATH}/main/main.cpp ) diff --git a/src/agent/main/Agent.cpp b/src/agent/main/Agent.cpp index 68883a7..d95b615 100644 --- a/src/agent/main/Agent.cpp +++ b/src/agent/main/Agent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * @file src/agent/main/Agent.cpp + * @file Agent.cpp * @author Adam Malinowski * @brief This file implements main class of ask user agent */ @@ -29,7 +29,7 @@ namespace AskUser { namespace Agent { -Agent::Agent() { +Agent::Agent() : m_cynaraTalker([&](Request *request) -> void { requestHandler(request); }) { init(); } @@ -44,7 +44,10 @@ void Agent::init() { } void Agent::run() { - // TODO: implement real task + m_cynaraTalker.start(); + + // TODO: wait for requests + while (true) { sleep(1); } @@ -58,6 +61,15 @@ void Agent::finish() { LOGD("Agent daemon has stopped commonly"); } +void Agent::requestHandler(Request *request) { + LOGD("Cynara request received:" + " type [" << request->type() << "]," + " id [" << request->id() << "]," + " data length: [" << request->data().size() << "]"); + + delete request; +} + } // namespace Agent } // namespace AskUser diff --git a/src/agent/main/Agent.h b/src/agent/main/Agent.h index 97fe825..6cfc49a 100644 --- a/src/agent/main/Agent.h +++ b/src/agent/main/Agent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -14,13 +14,16 @@ * limitations under the License. */ /** - * @file src/agent/main/Agent.h + * @file Agent.h * @author Adam Malinowski * @brief This file defines main class of ask user agent */ #pragma once +#include
+#include
+ namespace AskUser { namespace Agent { @@ -33,8 +36,12 @@ public: void run(); private: + CynaraTalker m_cynaraTalker; + void init(); void finish(); + + void requestHandler(Request *request); }; } // namespace Agent diff --git a/src/agent/main/CynaraTalker.cpp b/src/agent/main/CynaraTalker.cpp new file mode 100644 index 0000000..28efe12 --- /dev/null +++ b/src/agent/main/CynaraTalker.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 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 CynaraTalker.cpp + * @author Adam Malinowski + * @brief This file implements class of cynara talker + */ + +#include + +#include +#include +#include + +#include "CynaraTalker.h" + +namespace { + +class TypeException : std::exception { +public: + TypeException(const std::string &msg) : m_what(msg) {}; + virtual const char* what() const noexcept { + return m_what.c_str(); + } + +private: + std::string m_what; +}; + +AskUser::Agent::RequestType cynaraType2AgentType(cynara_agent_msg_type type) { + switch (type) { + case CYNARA_MSG_TYPE_ACTION: + return AskUser::Agent::RT_Action; + case CYNARA_MSG_TYPE_CANCEL: + return AskUser::Agent::RT_Cancel; + } + + throw TypeException("Unsupported request type: " + std::to_string(type) + + " received from cynara."); +} + +cynara_agent_msg_type agentType2CynaraType(AskUser::Agent::RequestType type) { + switch (type) { + case AskUser::Agent::RT_Action: + return CYNARA_MSG_TYPE_ACTION; + case AskUser::Agent::RT_Cancel: + return CYNARA_MSG_TYPE_CANCEL; + default: // let's make compiler happy + break; + } + + throw TypeException("Invalid response type: " + std::to_string(type) + " to send to cynara."); +} + +} + +namespace AskUser { + +namespace Agent { + +CynaraTalker::CynaraTalker(RequestHandler requestHandler) : m_requestHandler(requestHandler), + m_cynara(nullptr) { + m_future = m_threadFinished.get_future(); +} + +bool CynaraTalker::start() { + if (!m_requestHandler) { + LOGE("Empty request handler!"); + return false; + } + + m_thread = std::thread(&CynaraTalker::run, this); + return true; +} + +bool CynaraTalker::stop() { + // There is no possibility to stop this thread nicely when it waits for requests from cynara + // We can only try to get rid of thread + auto status = m_future.wait_for(std::chrono::milliseconds(10)); + if (status == std::future_status::ready) { + LOGD("Cynara thread finished and ready to join."); + m_thread.join(); + return true; + } + + LOGD("Cynara thread not finished."); + return false; +} + +void CynaraTalker::run() { + int ret = cynara_agent_initialize(&m_cynara, SupportedTypes::Agent::AgentType); + if (ret != CYNARA_API_SUCCESS) { + LOGE("Initialization of cynara structure failed with error: [" << ret << "]"); + m_requestHandler(new Request(RT_Close, 0, nullptr, 0)); // Notify agent he should die + return; + } + + void *data = nullptr; + + try { + while (true) { + cynara_agent_msg_type req_type; + cynara_agent_req_id req_id; + size_t data_size = 0; + + ret = cynara_agent_get_request(m_cynara, &req_type, &req_id, &data, &data_size); + if (ret != CYNARA_API_SUCCESS) { + LOGE("Receiving request from cynara failed with error: [" << ret << "]"); + m_requestHandler(new Request(RT_Close, 0, nullptr, 0)); + break; + } + + try { + m_requestHandler(new Request(cynaraType2AgentType(req_type), req_id, data, + data_size)); + } catch (const TypeException &e) { + LOGE("TypeException: <" << e.what() << "> Request dropped!"); + } + free(data); + data = nullptr; + } + } catch (const std::exception &e) { + LOGC("Unexpected exception: <" << e.what() << ">"); + } catch (...) { + LOGE("Unexpected unknown exception caught!"); + } + + free(data); + + std::unique_lock mlock(m_mutex); + ret = cynara_agent_finish(m_cynara); + m_cynara = nullptr; + if (ret != CYNARA_API_SUCCESS) { + LOGE("Finishing cynara connection failed with error: [" << ret << "]"); + } + + m_threadFinished.set_value(true); +} + +bool CynaraTalker::sendResponse(RequestType requestType, RequestId requestId, + const Cynara::PluginData &data) { + + std::unique_lock mlock(m_mutex); + + if (!m_cynara) { + LOGE("Trying to send response using uninitialized cynara connection!"); + return false; + } + + int ret; + try { + ret = cynara_agent_put_response(m_cynara, agentType2CynaraType(requestType), requestId, + data.size() ? data.data() : nullptr, data.size()); + } catch (const TypeException &e) { + LOGE("TypeException: <" << e.what() << "> Response dropped!"); + ret = CYNARA_API_INVALID_PARAM; + } + + if (ret != CYNARA_API_SUCCESS) { + LOGE("Sending response to cynara failed with error: [" << ret << "]"); + return false; + } + + return true; +} + +} // namespace Agent + +} // namespace AskUser diff --git a/src/agent/main/CynaraTalker.h b/src/agent/main/CynaraTalker.h new file mode 100644 index 0000000..3f45b96 --- /dev/null +++ b/src/agent/main/CynaraTalker.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 CynaraTalker.h + * @author Adam Malinowski + * @brief This file declares class representing request from cynara service + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include
+ +namespace AskUser { + +namespace Agent { + +typedef std::function RequestHandler; + +class CynaraTalker { +public: + CynaraTalker(RequestHandler requestHandler); + ~CynaraTalker() {} + + bool start(); + bool stop(); + + bool sendResponse(RequestType requestType, RequestId requestId, const Cynara::PluginData &data); + +private: + RequestHandler m_requestHandler; + cynara_agent *m_cynara; + std::thread m_thread; + std::mutex m_mutex; + std::promise m_threadFinished; + std::future m_future; + + void run(); +}; + +} // namespace Agent + +} // namespace AskUser -- 2.7.4