ADD_SUBDIRECTORY(logger)
ADD_SUBDIRECTORY(rmi)
ADD_SUBDIRECTORY(sdk)
-ADD_SUBDIRECTORY(transport)
# policy
ADD_SUBDIRECTORY(policy)
# limitations under the License
ADD_VIST_COMMON_LIBRARY(vist_rmi gateway.cpp
- remote.cpp)
+ remote.cpp
+ message.cpp)
+
+ADD_VIST_COMMON_LIBRARY(vist_rmi_impl impl/protocol.cpp)
FILE(GLOB RMI_TESTS "tests/*.cpp")
ADD_VIST_TEST(${RMI_TESTS})
+
+FILE(GLOB RMI_IMPL_TESTS "impl/tests/*.cpp")
+ADD_VIST_TEST(${RMI_IMPL_TESTS})
* See the License for the specific language governing permissions and
* limitations under the License
*/
-/*
- * @file gateway.cpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @brief Implementation of Server-side stub for exposing method.
- */
#include "gateway.hpp"
#include <vist/exception.hpp>
-#include <vist/transport/message.hpp>
-#include <vist/transport/server.hpp>
+#include <vist/rmi/message.hpp>
+#include <vist/rmi/impl/server.hpp>
#include <string>
namespace vist {
namespace rmi {
-using namespace vist::transport;
+using namespace vist::rmi::impl;
class Gateway::Impl {
public:
* See the License for the specific language governing permissions and
* limitations under the License
*/
-/*
- * @file gateway.hpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @brief Server-side stub for exposing method.
- */
#pragma once
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include "protocol.hpp"
+
+#include <vist/exception.hpp>
+#include <vist/logger.hpp>
+
+namespace vist {
+namespace rmi {
+namespace impl {
+
+using boost::asio::local::stream_protocol;
+
+class Client {
+public:
+ Client(const std::string& path) : socket(this->context)
+ {
+ try {
+ this->socket.connect(Protocol::Endpoint(path));
+ } catch(const std::exception& e) {
+ ERROR(VIST) << "Failed to connect socket: " << e.what();
+ std::rethrow_exception(std::current_exception());
+ }
+ }
+
+ inline Message request(Message& message)
+ {
+ return Protocol::Request(this->socket, message);
+ }
+
+private:
+ Protocol::Context context;
+ Protocol::Socket socket;
+};
+
+} // namespace impl
+} // namespace rmi
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#include "protocol.hpp"
+
+#include <vist/exception.hpp>
+#include <vist/logger.hpp>
+
+namespace vist {
+namespace rmi {
+namespace impl {
+
+Message Protocol::Recv(Socket& socket)
+{
+ DEBUG(VIST) << "Socket read event occured.";
+ Message::Header header;
+ const auto& headerBuffer = boost::asio::buffer(&header, sizeof(Message::Header));
+ auto readen = boost::asio::read(socket, headerBuffer);
+ if (readen != sizeof(Message::Header))
+ THROW(ErrCode::ProtocolBroken) << "Failed to receive message header.";
+
+ Message content(header);
+ const auto& contentBuffer = boost::asio::buffer(content.getBuffer());
+ readen = boost::asio::read(socket, contentBuffer);
+ if (readen != content.size())
+ THROW(ErrCode::ProtocolBroken) << "Failed to receive message content.";
+
+ content.disclose(content.signature);
+
+ return content;
+}
+
+void Protocol::Send(Socket& socket, Message& message)
+{
+ DEBUG(VIST) << "Socket write event occured.";
+ const auto& headerBuffer = boost::asio::buffer(&message.header,
+ sizeof(Message::Header));
+ auto written = boost::asio::write(socket, headerBuffer);
+ if (written != sizeof(Message::Header))
+ THROW(ErrCode::ProtocolBroken) << "Failed to send message header.";
+
+ const auto& contentBuffer = boost::asio::buffer(message.getBuffer(), message.size());
+ written = boost::asio::write(socket, contentBuffer);
+ if (written != message.size())
+ THROW(ErrCode::ProtocolBroken) << "Failed to send message content.";
+}
+
+Message Protocol::Request(Socket& socket, Message& message)
+{
+ Protocol::Send(socket, message);
+ return Protocol::Recv(socket);
+}
+
+void Protocol::Async::dispatch(const Task& task, std::atomic<bool>& polling)
+{
+ polling = true;
+ auto self = shared_from_this();
+ const auto& header = boost::asio::buffer(&this->message.header,
+ sizeof(Message::Header));
+ auto handler = [self, task, &polling](const auto& error, std::size_t size) {
+ if (error) {
+ if (error == boost::asio::error::eof) {
+ DEBUG(VIST) << "Socket EoF event occured.";
+ return;
+ } else {
+ THROW(ErrCode::RuntimeError) << error.message();
+ }
+ }
+
+ if (size != sizeof(Message::Header))
+ THROW(ErrCode::ProtocolBroken) << error.message();
+
+ /// Resize message buffer to revieved header length.
+ self->message.resize(self->message.size());
+
+ const auto& contentBuffer = boost::asio::buffer(self->message.getBuffer());
+ auto readen = boost::asio::read(self->socket, contentBuffer);
+ if (readen != self->message.size())
+ THROW(ErrCode::ProtocolBroken) << "Failed to receive message content."
+ << readen << ", " << self->message.size();
+
+ self->message.disclose(self->message.signature);
+ self->process(task, polling);
+ };
+
+ boost::asio::async_read(self->socket, header, handler);
+}
+
+void Protocol::Async::process(const Task& task, std::atomic<bool>& polling)
+{
+ bool raised = false;
+ std::string errMsg;
+ auto onError = [&raised, &errMsg](const std::string& message) {
+ ERROR(VIST) << "Failed to process task: " << message;
+ raised = true;
+ errMsg = message;
+ };
+
+ try {
+ /// Process dispatched task.
+ auto result = task(message);
+ this->message = result;
+ } catch (const vist::Exception<ErrCode>& e) {
+ onError(e.what());
+ } catch (const std::exception& e) {
+ onError(e.what());
+ }
+
+ if (raised)
+ this->message = Message(Message::Type::Error, errMsg);
+
+ auto self = shared_from_this();
+ const auto& headerBuffer = boost::asio::buffer(&this->message.header,
+ sizeof(Message::Header));
+ auto handler = [self, task, &polling](const auto& error, std::size_t size) {
+ if (error || size != sizeof(Message::Header))
+ THROW(ErrCode::ProtocolBroken) << "Failed to send message header: "
+ << error.message();
+
+ const auto& contentBuffer = boost::asio::buffer(self->message.getBuffer());
+ auto written = boost::asio::write(self->socket, contentBuffer);
+ if (written != self->message.size())
+ THROW(ErrCode::ProtocolBroken) << "Failed to send message content.";
+
+ /// Re-dispatch for next request.
+ self->dispatch(task, polling);
+ };
+
+ boost::asio::async_write(self->socket, headerBuffer, handler);
+}
+
+} // namespace impl
+} // namespace rmi
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include <vist/rmi/message.hpp>
+
+#include <atomic>
+#include <functional>
+
+#include <boost/asio.hpp>
+
+namespace vist {
+namespace rmi {
+namespace impl {
+
+struct Protocol {
+ using Acceptor = boost::asio::local::stream_protocol::acceptor;
+ using Context = boost::asio::io_service;
+ using Endpoint = boost::asio::local::stream_protocol::endpoint;
+ using Socket = boost::asio::local::stream_protocol::socket;
+ using Task = std::function<Message(Message&)>;
+
+ static Message Recv(Socket& socket);
+ static void Send(Socket& socket, Message& message);
+
+ static Message Request(Socket& socket, Message& message);
+
+ /// Passing shared_from_this() to lambda() guarantees
+ /// that the lambda() always refer to a live object.
+ class Async : public std::enable_shared_from_this<Async> {
+ public:
+ explicit Async(Context& context) : socket(context) {}
+ void dispatch(const Task& task, std::atomic<bool>& polling);
+ void process(const Task& task, std::atomic<bool>& polling);
+
+ inline Socket& getSocket()
+ {
+ return this->socket;
+ }
+
+ private:
+ Message message;
+ Socket socket;
+ };
+};
+
+} // namespace impl
+} // namespace rmi
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#pragma once
+
+#include "protocol.hpp"
+
+#include <vist/timer.hpp>
+#include <vist/exception.hpp>
+#include <vist/logger.hpp>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <thread>
+
+#include <errno.h>
+#include <unistd.h>
+
+namespace vist {
+namespace rmi {
+namespace impl {
+
+class Server {
+public:
+ Server(const std::string& path, const Protocol::Task& task) : polling(false)
+ {
+ errno = 0;
+ if (::unlink(path.c_str()) == -1 && errno != ENOENT)
+ THROW(ErrCode::RuntimeError) << "Failed to remove file.";
+
+ this->acceptor = std::make_unique<Protocol::Acceptor>(this->context,
+ Protocol::Endpoint(path));
+ this->accept(task);
+ }
+
+ inline void accept(const Protocol::Task& task)
+ {
+ auto asyncSession = std::make_shared<Protocol::Async>(this->context);
+ auto handler = [this, asyncSession, task](const auto& error) {
+ DEBUG(VIST) << "New session is accepted.";
+
+ if (error)
+ THROW(ErrCode::RuntimeError) << error.message();
+
+ asyncSession->dispatch(task, this->polling);
+
+ this->accept(task);
+ };
+ this->acceptor->async_accept(asyncSession->getSocket(), handler);
+ }
+
+ inline void run(unsigned int timeout = 0, Timer::Predicate condition = nullptr)
+ {
+ if (timeout > 0) {
+ auto stopper = [this]() {
+ INFO(VIST) << "There are no sessions. And timeout is occured.";
+ this->context.stop();
+ };
+
+ auto wrapper = [this, condition]() -> bool {
+ if (condition)
+ return condition() && polling == false;
+
+ return polling == false;
+ };
+
+ Timer::ExecOnce(stopper, wrapper, timeout);
+ }
+
+ this->context.run();
+ }
+
+ inline void stop()
+ {
+ this->context.stop();
+ }
+
+private:
+ Protocol::Context context;
+ std::unique_ptr<Protocol::Acceptor> acceptor;
+
+ /// check for session is maintained
+ std::atomic<bool> polling;
+};
+
+} // namespace impl
+} // namespace rmi
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#include <vist/rmi/message.hpp>
+#include <vist/rmi/impl/protocol.hpp>
+
+#include <string>
+#include <thread>
+
+#include <gtest/gtest.h>
+#include <boost/asio.hpp>
+
+#include <unistd.h>
+
+using namespace vist::rmi;
+using namespace vist::rmi::impl;
+using boost::asio::local::stream_protocol;
+
+namespace {
+
+/// Request variables
+std::string requestSignature = "request signature";
+int request1 = 100;
+bool request2 = true;
+std::string request3 = "request argument";
+
+/// Response variables
+std::string responseSignature = "response signature";
+int response1 = 300;
+bool response2 = false;
+std::string response3 = "response argument";
+
+} // anonymous namespace
+
+TEST(ProtocolTests, sync_server_sync_client)
+{
+ std::string sockPath = "vist-test.sock";
+ ::unlink(sockPath.c_str());
+
+ /// Server configuration
+ boost::asio::io_service context;
+ stream_protocol::acceptor acceptor(context, stream_protocol::endpoint(sockPath));
+ stream_protocol::socket sock(context);
+
+ auto handler = [&](const auto& error) {
+ EXPECT_EQ(error, boost::system::errc::success);
+
+ Message request = Protocol::Recv(sock);
+ EXPECT_EQ(request.signature, requestSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ request.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(request1, recv1);
+ EXPECT_EQ(request2, recv2);
+ EXPECT_EQ(request3, recv3);
+
+ Message reply(Message::Type::Reply, responseSignature);
+ reply.enclose(response1, response2, response3);
+ Protocol::Send(sock, reply);
+ };
+ acceptor.async_accept(sock, handler);
+
+ auto serverThread = std::thread([&]() {
+ context.run();
+ });
+
+ { /// Client configuration
+ boost::asio::io_service context;
+ stream_protocol::socket sock(context);
+ sock.connect(stream_protocol::endpoint(sockPath));
+
+ Message request(Message::Type::MethodCall, requestSignature);
+ request.enclose(request1, request2, request3);
+
+ auto reply = Protocol::Request(sock, request);
+ EXPECT_EQ(reply.signature, responseSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ reply.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(response1, recv1);
+ EXPECT_EQ(response2, recv2);
+ EXPECT_EQ(response3, recv3);
+ }
+
+ context.stop();
+
+ if (serverThread.joinable())
+ serverThread.join();
+}
+
+/* example without polling memeber variable
+TEST(ProtocolTests, async_server_sync_client)
+{
+ std::string sockPath = "vist-test.sock";
+ ::unlink(sockPath.c_str());
+
+ /// Server configuration
+ boost::asio::io_service context;
+ stream_protocol::acceptor acceptor(context, stream_protocol::endpoint(sockPath));
+
+ auto async = std::make_shared<Protocol::Async>(context);
+ auto handler = [&](const auto& error) {
+ EXPECT_EQ(error, boost::system::errc::success);
+ auto task = [&](auto& message) -> Message {
+ EXPECT_EQ(message.signature, requestSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ message.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(request1, recv1);
+ EXPECT_EQ(request2, recv2);
+ EXPECT_EQ(request3, recv3);
+
+ Message reply(Message::Type::Reply, responseSignature);
+ reply.enclose(response1, response2, response3);
+ return reply;
+ };
+
+ async->dispatch(task);
+ };
+ acceptor.async_accept(async->getSocket(), handler);
+
+ auto serverThread = std::thread([&]() {
+ context.run();
+ });
+
+ { /// Client configuration
+ boost::asio::io_service context;
+ stream_protocol::socket sock(context);
+ sock.connect(stream_protocol::endpoint(sockPath));
+
+ Message request(Message::Type::MethodCall, requestSignature);
+ request.enclose(request1, request2, request3);
+
+ auto requestClosure = [&]() {
+ auto reply = Protocol::Request(sock, request);
+ EXPECT_EQ(reply.signature, responseSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ reply.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(response1, recv1);
+ EXPECT_EQ(response2, recv2);
+ EXPECT_EQ(response3, recv3);
+ };
+
+ for (int i = 0; i < 3; i++)
+ requestClosure();
+ }
+
+ context.stop();
+
+ if (serverThread.joinable())
+ serverThread.join();
+}
+*/
--- /dev/null
+/*
+ * Copyright (c) 2019 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
+ */
+
+#include <vist/rmi/message.hpp>
+#include <vist/rmi/impl/server.hpp>
+#include <vist/rmi/impl/client.hpp>
+
+#include <string>
+#include <thread>
+
+#include <boost/asio.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace vist::rmi;
+using namespace vist::rmi::impl;
+using boost::asio::local::stream_protocol;
+
+namespace {
+
+/// Request variables
+std::string requestSignature = "request signature";
+int request1 = 100;
+bool request2 = true;
+std::string request3 = "request argument";
+
+/// Response variables
+std::string responseSignature = "response signature";
+int response1 = 300;
+bool response2 = false;
+std::string response3 = "response argument";
+
+} // anonymous namespace
+
+TEST(ServerClientTests, server)
+{
+ std::string sockPath = "vist-test.sock";
+
+ auto task = [&](Message& message) -> Message {
+ EXPECT_EQ(message.signature, requestSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ message.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(request1, recv1);
+ EXPECT_EQ(request2, recv2);
+ EXPECT_EQ(request3, recv3);
+
+ Message reply(Message::Type::Reply, responseSignature);
+ reply.enclose(response1, response2, response3);
+ return reply;
+ };
+
+ Server server(sockPath, task);
+ auto serverThread = std::thread([&]() {
+ server.run();
+ });
+
+ { /// Client configuration
+ auto clientClosure = [&]() {
+ Client client(sockPath);
+
+ Message message(Message::Type::MethodCall, requestSignature);
+ message.enclose(request1, request2, request3);
+
+ for (int i = 0; i < 3; i++) {
+ auto reply = client.request(message);
+ EXPECT_EQ(reply.signature, responseSignature);
+
+ int recv1;
+ bool recv2;
+ std::string recv3;
+ reply.disclose(recv1, recv2, recv3);
+ EXPECT_EQ(response1, recv1);
+ EXPECT_EQ(response2, recv2);
+ EXPECT_EQ(response3, recv3);
+ }
+ };
+
+ for (int i = 0; i < 3; i++)
+ clientClosure();
+ }
+
+ server.stop();
+
+ if (serverThread.joinable())
+ serverThread.join();
+}
--- /dev/null
+/*
+ * Copyright (c) 2018-present 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
+ */
+
+#include "message.hpp"
+
+namespace vist {
+namespace rmi {
+
+Message::Message(unsigned int type, const std::string& signature) :
+ header({0, type, signature.size()}),
+ signature(signature)
+{
+ this->enclose(signature);
+}
+
+Message::Message(Header header) : header(header)
+{
+ this->buffer.resize(this->header.length);
+}
+
+bool Message::success() const noexcept
+{
+ return !error();
+}
+
+bool Message::error() const noexcept
+{
+ return this->header.type == Type::Error;
+}
+
+std::string Message::what() const noexcept
+{
+ return this->signature;
+}
+
+std::size_t Message::size(void) const noexcept
+{
+ return this->header.length;
+}
+
+void Message::resize(std::size_t size)
+{
+ this->buffer.resize(size);
+}
+
+std::vector<unsigned char>& Message::getBuffer(void) noexcept
+{
+ return this->buffer.getBuffer();
+}
+
+} // namespace rmi
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2018-present 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
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <vist/archive.hpp>
+
+namespace vist {
+namespace rmi {
+
+struct Message final {
+ enum Type : unsigned int {
+ Invalid,
+ MethodCall,
+ Reply,
+ Error,
+ Signal
+ };
+
+ struct Header {
+ unsigned int id;
+ unsigned int type;
+ size_t length;
+ };
+
+ explicit Message(void) = default;
+ explicit Message(unsigned int type, const std::string& signature);
+ explicit Message(Header header);
+
+ ~Message(void) noexcept = default;
+
+ Message(const Message&) = default;
+ Message(Message&&) = default;
+
+ Message& operator=(const Message&) = default;
+ Message& operator=(Message&&) = default;
+
+ template<typename... Args>
+ void enclose(Args&&... args);
+ template<typename... Args>
+ void disclose(Args&... args);
+
+ bool success() const noexcept;
+ bool error() const noexcept;
+ std::string what() const noexcept;
+
+ std::size_t size(void) const noexcept;
+ void resize(std::size_t size);
+ std::vector<unsigned char>& getBuffer(void) noexcept;
+
+ Header header;
+ std::string signature;
+ Archive buffer;
+};
+
+template<typename... Args>
+void Message::enclose(Args&&... args)
+{
+ this->buffer.pack(std::forward<Args>(args)...);
+ header.length = this->buffer.size();
+}
+
+template<typename... Args>
+void Message::disclose(Args&... args)
+{
+ this->buffer.unpack(args...);
+}
+
+} // namespace rmi
+} // namespace vist
* See the License for the specific language governing permissions and
* limitations under the License
*/
-/*
- * @file remote.cpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @brief Implementation of remote.
- */
#include "remote.hpp"
-#include <vist/transport/client.hpp>
+#include <vist/rmi/impl/client.hpp>
#include <string>
#include <mutex>
namespace vist {
namespace rmi {
-using namespace vist::transport;
+using namespace vist::rmi::impl;
class Remote::Impl {
public:
* See the License for the specific language governing permissions and
* limitations under the License
*/
-/*
- * @file remote.hpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @brief Client-side stub for invoking remote method.
- */
#pragma once
#include <vist/exception.hpp>
-#include <vist/transport/message.hpp>
+#include <vist/rmi/message.hpp>
#include <string>
#include <memory>
namespace vist {
namespace rmi {
-using namespace vist::transport;
-
class Remote final {
public:
explicit Remote(const std::string& path);
* See the License for the specific language governing permissions and
* limitations under the License
*/
-/*
- * @file rmi.cpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief Testcases of rmi.
- */
-
#include <vist/rmi/gateway.hpp>
#include <vist/rmi/remote.hpp>
+++ /dev/null
-# Copyright (c) 2019 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
-
-ADD_VIST_COMMON_LIBRARY(vist_transport message.cpp
- protocol.cpp)
-
-FILE(GLOB TRANSPORT_TESTS "tests/*.cpp")
-ADD_VIST_TEST(${TRANSPORT_TESTS})
+++ /dev/null
-/*
- * Copyright (c) 2019 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.hpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief Protocol compliant client.
- */
-
-#pragma once
-
-#include <vist/exception.hpp>
-#include <vist/logger.hpp>
-#include <vist/transport/protocol.hpp>
-
-namespace vist {
-namespace transport {
-
-using boost::asio::local::stream_protocol;
-
-class Client {
-public:
- Client(const std::string& path) : socket(this->context)
- {
- try {
- this->socket.connect(Protocol::Endpoint(path));
- } catch(const std::exception& e) {
- ERROR(VIST) << "Failed to connect socket: " << e.what();
- std::rethrow_exception(std::current_exception());
- }
- }
-
- inline Message request(Message& message)
- {
- return Protocol::Request(this->socket, message);
- }
-
-private:
- Protocol::Context context;
- Protocol::Socket socket;
-};
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2018-present 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 message.cpp
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief Implementaion of message.
- */
-
-#include "message.hpp"
-
-namespace vist {
-namespace transport {
-
-Message::Message(unsigned int type, const std::string& signature) :
- header({0, type, signature.size()}),
- signature(signature)
-{
- this->enclose(signature);
-}
-
-Message::Message(Header header) : header(header)
-{
- this->buffer.resize(this->header.length);
-}
-
-bool Message::success() const noexcept
-{
- return !error();
-}
-
-bool Message::error() const noexcept
-{
- return this->header.type == Type::Error;
-}
-
-std::string Message::what() const noexcept
-{
- return this->signature;
-}
-
-std::size_t Message::size(void) const noexcept
-{
- return this->header.length;
-}
-
-void Message::resize(std::size_t size)
-{
- this->buffer.resize(size);
-}
-
-std::vector<unsigned char>& Message::getBuffer(void) noexcept
-{
- return this->buffer.getBuffer();
-}
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2018-present 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 message.hpp
- * @author Jaemin Ryu (jm77.ryu@samsung.com)
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief The unit of socket communication.
- */
-
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include <vist/archive.hpp>
-
-namespace vist {
-namespace transport {
-
-struct Message final {
- enum Type : unsigned int {
- Invalid,
- MethodCall,
- Reply,
- Error,
- Signal
- };
-
- struct Header {
- unsigned int id;
- unsigned int type;
- size_t length;
- };
-
- explicit Message(void) = default;
- explicit Message(unsigned int type, const std::string& signature);
- explicit Message(Header header);
-
- ~Message(void) noexcept = default;
-
- Message(const Message&) = default;
- Message(Message&&) = default;
-
- Message& operator=(const Message&) = default;
- Message& operator=(Message&&) = default;
-
- template<typename... Args>
- void enclose(Args&&... args);
- template<typename... Args>
- void disclose(Args&... args);
-
- bool success() const noexcept;
- bool error() const noexcept;
- std::string what() const noexcept;
-
- std::size_t size(void) const noexcept;
- void resize(std::size_t size);
- std::vector<unsigned char>& getBuffer(void) noexcept;
-
- Header header;
- std::string signature;
- Archive buffer;
-};
-
-template<typename... Args>
-void Message::enclose(Args&&... args)
-{
- this->buffer.pack(std::forward<Args>(args)...);
- header.length = this->buffer.size();
-}
-
-template<typename... Args>
-void Message::disclose(Args&... args)
-{
- this->buffer.unpack(args...);
-}
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 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
- */
-
-#include "protocol.hpp"
-
-#include <vist/exception.hpp>
-#include <vist/logger.hpp>
-
-namespace vist {
-namespace transport {
-
-Message Protocol::Recv(Socket& socket)
-{
- DEBUG(VIST) << "Socket read event occured.";
- Message::Header header;
- const auto& headerBuffer = boost::asio::buffer(&header, sizeof(Message::Header));
- auto readen = boost::asio::read(socket, headerBuffer);
- if (readen != sizeof(Message::Header))
- THROW(ErrCode::ProtocolBroken) << "Failed to receive message header.";
-
- Message content(header);
- const auto& contentBuffer = boost::asio::buffer(content.getBuffer());
- readen = boost::asio::read(socket, contentBuffer);
- if (readen != content.size())
- THROW(ErrCode::ProtocolBroken) << "Failed to receive message content.";
-
- content.disclose(content.signature);
-
- return content;
-}
-
-void Protocol::Send(Socket& socket, Message& message)
-{
- DEBUG(VIST) << "Socket write event occured.";
- const auto& headerBuffer = boost::asio::buffer(&message.header,
- sizeof(Message::Header));
- auto written = boost::asio::write(socket, headerBuffer);
- if (written != sizeof(Message::Header))
- THROW(ErrCode::ProtocolBroken) << "Failed to send message header.";
-
- const auto& contentBuffer = boost::asio::buffer(message.getBuffer(), message.size());
- written = boost::asio::write(socket, contentBuffer);
- if (written != message.size())
- THROW(ErrCode::ProtocolBroken) << "Failed to send message content.";
-}
-
-Message Protocol::Request(Socket& socket, Message& message)
-{
- Protocol::Send(socket, message);
- return Protocol::Recv(socket);
-}
-
-void Protocol::Async::dispatch(const Task& task, std::atomic<bool>& polling)
-{
- polling = true;
- auto self = shared_from_this();
- const auto& header = boost::asio::buffer(&this->message.header,
- sizeof(Message::Header));
- auto handler = [self, task, &polling](const auto& error, std::size_t size) {
- if (error) {
- if (error == boost::asio::error::eof) {
- DEBUG(VIST) << "Socket EoF event occured.";
- return;
- } else {
- THROW(ErrCode::RuntimeError) << error.message();
- }
- }
-
- if (size != sizeof(Message::Header))
- THROW(ErrCode::ProtocolBroken) << error.message();
-
- /// Resize message buffer to revieved header length.
- self->message.resize(self->message.size());
-
- const auto& contentBuffer = boost::asio::buffer(self->message.getBuffer());
- auto readen = boost::asio::read(self->socket, contentBuffer);
- if (readen != self->message.size())
- THROW(ErrCode::ProtocolBroken) << "Failed to receive message content."
- << readen << ", " << self->message.size();
-
- self->message.disclose(self->message.signature);
- self->process(task, polling);
- };
-
- boost::asio::async_read(self->socket, header, handler);
-}
-
-void Protocol::Async::process(const Task& task, std::atomic<bool>& polling)
-{
- bool raised = false;
- std::string errMsg;
- auto onError = [&raised, &errMsg](const std::string& message) {
- ERROR(VIST) << "Failed to process task: " << message;
- raised = true;
- errMsg = message;
- };
-
- try {
- /// Process dispatched task.
- auto result = task(message);
- this->message = result;
- } catch (const vist::Exception<ErrCode>& e) {
- onError(e.what());
- } catch (const std::exception& e) {
- onError(e.what());
- }
-
- if (raised)
- this->message = Message(Message::Type::Error, errMsg);
-
- auto self = shared_from_this();
- const auto& headerBuffer = boost::asio::buffer(&this->message.header,
- sizeof(Message::Header));
- auto handler = [self, task, &polling](const auto& error, std::size_t size) {
- if (error || size != sizeof(Message::Header))
- THROW(ErrCode::ProtocolBroken) << "Failed to send message header: "
- << error.message();
-
- const auto& contentBuffer = boost::asio::buffer(self->message.getBuffer());
- auto written = boost::asio::write(self->socket, contentBuffer);
- if (written != self->message.size())
- THROW(ErrCode::ProtocolBroken) << "Failed to send message content.";
-
- /// Re-dispatch for next request.
- self->dispatch(task, polling);
- };
-
- boost::asio::async_write(self->socket, headerBuffer, handler);
-}
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 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 protocol.hpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief Socket communication protocol between server and client.
- */
-
-#pragma once
-
-#include <vist/transport/message.hpp>
-
-#include <atomic>
-#include <functional>
-
-#include <boost/asio.hpp>
-
-namespace vist {
-namespace transport {
-
-struct Protocol {
- using Acceptor = boost::asio::local::stream_protocol::acceptor;
- using Context = boost::asio::io_service;
- using Endpoint = boost::asio::local::stream_protocol::endpoint;
- using Socket = boost::asio::local::stream_protocol::socket;
- using Task = std::function<Message(Message&)>;
-
- static Message Recv(Socket& socket);
- static void Send(Socket& socket, Message& message);
-
- static Message Request(Socket& socket, Message& message);
-
- /// Passing shared_from_this() to lambda() guarantees
- /// that the lambda() always refer to a live object.
- class Async : public std::enable_shared_from_this<Async> {
- public:
- explicit Async(Context& context) : socket(context) {}
- void dispatch(const Task& task, std::atomic<bool>& polling);
- void process(const Task& task, std::atomic<bool>& polling);
-
- inline Socket& getSocket()
- {
- return this->socket;
- }
-
- private:
- Message message;
- Socket socket;
- };
-};
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 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 server.hpp
- * @author Sangwan Kwon (sangwan.kwon@samsung.com)
- * @brief Protocol compliant server.
- */
-
-#pragma once
-
-#include <vist/timer.hpp>
-#include <vist/exception.hpp>
-#include <vist/logger.hpp>
-#include <vist/transport/protocol.hpp>
-
-#include <memory>
-#include <atomic>
-#include <thread>
-#include <chrono>
-
-#include <unistd.h>
-#include <errno.h>
-
-namespace vist {
-namespace transport {
-
-class Server {
-public:
- Server(const std::string& path, const Protocol::Task& task) : polling(false)
- {
- errno = 0;
- if (::unlink(path.c_str()) == -1 && errno != ENOENT)
- THROW(ErrCode::RuntimeError) << "Failed to remove file.";
-
- this->acceptor = std::make_unique<Protocol::Acceptor>(this->context,
- Protocol::Endpoint(path));
- this->accept(task);
- }
-
- inline void accept(const Protocol::Task& task)
- {
- auto asyncSession = std::make_shared<Protocol::Async>(this->context);
- auto handler = [this, asyncSession, task](const auto& error) {
- DEBUG(VIST) << "New session is accepted.";
-
- if (error)
- THROW(ErrCode::RuntimeError) << error.message();
-
- asyncSession->dispatch(task, this->polling);
-
- this->accept(task);
- };
- this->acceptor->async_accept(asyncSession->getSocket(), handler);
- }
-
- inline void run(unsigned int timeout = 0, Timer::Predicate condition = nullptr)
- {
- if (timeout > 0) {
- auto stopper = [this]() {
- INFO(VIST) << "There are no sessions. And timeout is occured.";
- this->context.stop();
- };
-
- auto wrapper = [this, condition]() -> bool {
- if (condition)
- return condition() && polling == false;
-
- return polling == false;
- };
-
- Timer::ExecOnce(stopper, wrapper, timeout);
- }
-
- this->context.run();
- }
-
- inline void stop()
- {
- this->context.stop();
- }
-
-private:
- Protocol::Context context;
- std::unique_ptr<Protocol::Acceptor> acceptor;
-
- /// check for session is maintained
- std::atomic<bool> polling;
-};
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 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
- */
-
-#pragma once
-
-#include <vist/logger.hpp>
-#include <vist/exception.hpp>
-
-#include <systemd/sd-daemon.h>
-
-namespace vist {
-namespace transport {
-
-class SystemdSocket {
-public:
- static int Create(const std::string& path)
- {
- static int fds = -1;
-
- if (fds == -1)
- fds = ::sd_listen_fds(0);
-
- if (fds < 0)
- THROW(ErrCode::RuntimeError) << "Failed to get listened systemd fds.";
-
- for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; ++fd) {
- if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) {
- INFO(VIST) << "Systemd socket of service is found with fd: " << fd;
- return fd;
- }
- }
-
- THROW(ErrCode::RuntimeError) << "Failed to find listened systemd fds.";
- }
-};
-
-} // namespace transport
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 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
- */
-
-#include <vist/transport/protocol.hpp>
-
-#include <string>
-#include <thread>
-
-#include <gtest/gtest.h>
-#include <boost/asio.hpp>
-
-#include <unistd.h>
-
-using namespace vist::transport;
-using boost::asio::local::stream_protocol;
-
-namespace {
-
-/// Request variables
-std::string requestSignature = "request signature";
-int request1 = 100;
-bool request2 = true;
-std::string request3 = "request argument";
-
-/// Response variables
-std::string responseSignature = "response signature";
-int response1 = 300;
-bool response2 = false;
-std::string response3 = "response argument";
-
-} // anonymous namespace
-
-TEST(ProtocolTests, sync_server_sync_client)
-{
- std::string sockPath = "vist-test.sock";
- ::unlink(sockPath.c_str());
-
- /// Server configuration
- boost::asio::io_service context;
- stream_protocol::acceptor acceptor(context, stream_protocol::endpoint(sockPath));
- stream_protocol::socket sock(context);
-
- auto handler = [&](const auto& error) {
- EXPECT_EQ(error, boost::system::errc::success);
-
- Message request = Protocol::Recv(sock);
- EXPECT_EQ(request.signature, requestSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- request.disclose(recv1, recv2, recv3);
- EXPECT_EQ(request1, recv1);
- EXPECT_EQ(request2, recv2);
- EXPECT_EQ(request3, recv3);
-
- Message reply(Message::Type::Reply, responseSignature);
- reply.enclose(response1, response2, response3);
- Protocol::Send(sock, reply);
- };
- acceptor.async_accept(sock, handler);
-
- auto serverThread = std::thread([&]() {
- context.run();
- });
-
- { /// Client configuration
- boost::asio::io_service context;
- stream_protocol::socket sock(context);
- sock.connect(stream_protocol::endpoint(sockPath));
-
- Message request(Message::Type::MethodCall, requestSignature);
- request.enclose(request1, request2, request3);
-
- auto reply = Protocol::Request(sock, request);
- EXPECT_EQ(reply.signature, responseSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- reply.disclose(recv1, recv2, recv3);
- EXPECT_EQ(response1, recv1);
- EXPECT_EQ(response2, recv2);
- EXPECT_EQ(response3, recv3);
- }
-
- context.stop();
-
- if (serverThread.joinable())
- serverThread.join();
-}
-
-/* example without polling memeber variable
-TEST(ProtocolTests, async_server_sync_client)
-{
- std::string sockPath = "vist-test.sock";
- ::unlink(sockPath.c_str());
-
- /// Server configuration
- boost::asio::io_service context;
- stream_protocol::acceptor acceptor(context, stream_protocol::endpoint(sockPath));
-
- auto async = std::make_shared<Protocol::Async>(context);
- auto handler = [&](const auto& error) {
- EXPECT_EQ(error, boost::system::errc::success);
- auto task = [&](auto& message) -> Message {
- EXPECT_EQ(message.signature, requestSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- message.disclose(recv1, recv2, recv3);
- EXPECT_EQ(request1, recv1);
- EXPECT_EQ(request2, recv2);
- EXPECT_EQ(request3, recv3);
-
- Message reply(Message::Type::Reply, responseSignature);
- reply.enclose(response1, response2, response3);
- return reply;
- };
-
- async->dispatch(task);
- };
- acceptor.async_accept(async->getSocket(), handler);
-
- auto serverThread = std::thread([&]() {
- context.run();
- });
-
- { /// Client configuration
- boost::asio::io_service context;
- stream_protocol::socket sock(context);
- sock.connect(stream_protocol::endpoint(sockPath));
-
- Message request(Message::Type::MethodCall, requestSignature);
- request.enclose(request1, request2, request3);
-
- auto requestClosure = [&]() {
- auto reply = Protocol::Request(sock, request);
- EXPECT_EQ(reply.signature, responseSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- reply.disclose(recv1, recv2, recv3);
- EXPECT_EQ(response1, recv1);
- EXPECT_EQ(response2, recv2);
- EXPECT_EQ(response3, recv3);
- };
-
- for (int i = 0; i < 3; i++)
- requestClosure();
- }
-
- context.stop();
-
- if (serverThread.joinable())
- serverThread.join();
-}
-*/
+++ /dev/null
-/*
- * Copyright (c) 2019 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
- */
-
-#include <vist/transport/server.hpp>
-#include <vist/transport/client.hpp>
-
-#include <string>
-#include <thread>
-
-#include <boost/asio.hpp>
-
-#include <gtest/gtest.h>
-
-using namespace vist::transport;
-using boost::asio::local::stream_protocol;
-
-namespace {
-
-/// Request variables
-std::string requestSignature = "request signature";
-int request1 = 100;
-bool request2 = true;
-std::string request3 = "request argument";
-
-/// Response variables
-std::string responseSignature = "response signature";
-int response1 = 300;
-bool response2 = false;
-std::string response3 = "response argument";
-
-} // anonymous namespace
-
-TEST(ServerClientTests, server)
-{
- std::string sockPath = "vist-test.sock";
-
- auto task = [&](Message& message) -> Message {
- EXPECT_EQ(message.signature, requestSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- message.disclose(recv1, recv2, recv3);
- EXPECT_EQ(request1, recv1);
- EXPECT_EQ(request2, recv2);
- EXPECT_EQ(request3, recv3);
-
- Message reply(Message::Type::Reply, responseSignature);
- reply.enclose(response1, response2, response3);
- return reply;
- };
-
- Server server(sockPath, task);
- auto serverThread = std::thread([&]() {
- server.run();
- });
-
- { /// Client configuration
- auto clientClosure = [&]() {
- Client client(sockPath);
-
- Message message(Message::Type::MethodCall, requestSignature);
- message.enclose(request1, request2, request3);
-
- for (int i = 0; i < 3; i++) {
- auto reply = client.request(message);
- EXPECT_EQ(reply.signature, responseSignature);
-
- int recv1;
- bool recv2;
- std::string recv3;
- reply.disclose(recv1, recv2, recv3);
- EXPECT_EQ(response1, recv1);
- EXPECT_EQ(response2, recv2);
- EXPECT_EQ(response3, recv3);
- }
- };
-
- for (int i = 0; i < 3; i++)
- clientClosure();
- }
-
- server.stop();
-
- if (serverThread.joinable())
- serverThread.join();
-}