diff --git a/CMakeLists.txt b/CMakeLists.txt index 99beea0d..c785040c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,8 @@ add_library(oatpp network/virtual_/Pipe.hpp network/virtual_/Socket.cpp network/virtual_/Socket.hpp + network/virtual_/Interface.cpp + network/virtual_/Interface.hpp parser/json/mapping/Deserializer.cpp parser/json/mapping/Deserializer.hpp parser/json/mapping/ObjectMapper.cpp @@ -265,6 +267,8 @@ if(OATPP_BUILD_TESTS) test/parser/json/mapping/DTOMapperTest.hpp test/network/virtual_/PipeTest.cpp test/network/virtual_/PipeTest.hpp + test/network/virtual_/InterfaceTest.cpp + test/network/virtual_/InterfaceTest.hpp ) target_link_libraries(oatppAllTests PRIVATE oatpp) set_target_properties(oatppAllTests PROPERTIES diff --git a/core/collection/LinkedList.hpp b/core/collection/LinkedList.hpp index 0f9e61b5..67ada055 100644 --- a/core/collection/LinkedList.hpp +++ b/core/collection/LinkedList.hpp @@ -196,9 +196,8 @@ public: T result = node->data; destroyNode(node); return result; - }else{ - return T::empty(); } + throw std::runtime_error("[oatpp::collection::LinkedList::popFront()]: index out of bounds"); } const T& getFirst() const{ diff --git a/network/virtual_/Interface.hpp b/network/virtual_/Interface.hpp index b7478776..750f41ee 100644 --- a/network/virtual_/Interface.hpp +++ b/network/virtual_/Interface.hpp @@ -25,9 +25,101 @@ #ifndef oatpp_network_virtual__Interface_hpp #define oatpp_network_virtual__Interface_hpp +#include "./Socket.hpp" + +#include "oatpp/core/collection/LinkedList.hpp" + namespace oatpp { namespace network { namespace virtual_ { +class Interface : public oatpp::base::Controllable { +public: + class ConnectionSubmission { + private: + std::shared_ptr m_socket; + std::mutex m_mutex; + std::condition_variable m_condition; + bool m_pending; + public: + + ConnectionSubmission() + : m_pending(true) + {} + + void setSocket(const std::shared_ptr& socket) { + m_socket = socket; + m_condition.notify_one(); + } + + std::shared_ptr getSocket() { + std::unique_lock lock(m_mutex); + while (!m_socket && m_pending) { + m_condition.wait(lock); + } + return m_socket; + } + + std::shared_ptr getSocketNonBlocking() { + return m_socket; + } + + bool isPending() { + return m_pending; + } + + }; + +private: + + std::shared_ptr acceptSubmission(const std::shared_ptr& submission) { + + auto pipeIn = Pipe::createShared(); + auto pipeOut = Pipe::createShared(); + + auto serverSocket = Socket::createShared(pipeIn, pipeOut); + auto clientSocket = Socket::createShared(pipeOut, pipeIn); + + submission->setSocket(clientSocket); + + return serverSocket; + + } + +private: + std::mutex m_mutex; + std::condition_variable m_condition; + oatpp::collection::LinkedList> m_submissions; +public: + + std::shared_ptr connect() { + auto submission = std::make_shared(); + + { + std::lock_guard lock(m_mutex); + m_submissions.pushBack(submission); + } + + m_condition.notify_one(); + return submission; + } + + std::shared_ptr accept() { + std::unique_lock lock(m_mutex); + while (m_submissions.getFirstNode() == nullptr) { + m_condition.wait(lock); + } + return acceptSubmission(m_submissions.popFront()); + } + + std::shared_ptr acceptNonBlocking() { + std::lock_guard lock(m_mutex); + if(m_submissions.getFirstNode() == nullptr) { + return acceptSubmission(m_submissions.popFront()); + } + return nullptr; + } + +}; }}} diff --git a/network/virtual_/Pipe.cpp b/network/virtual_/Pipe.cpp index 60ad60f1..7bebccb2 100644 --- a/network/virtual_/Pipe.cpp +++ b/network/virtual_/Pipe.cpp @@ -34,14 +34,14 @@ os::io::Library::v_size Pipe::Reader::read(void *data, os::io::Library::v_size c if(m_nonBlocking) { if(pipe.m_buffer.availableToRead() > 0) { result = pipe.m_buffer.read(data, count); - } else if(pipe.m_alive) { + } else if(pipe.m_open) { result = oatpp::data::stream::Errors::ERROR_IO_WAIT_RETRY; } else { result = oatpp::data::stream::Errors::ERROR_IO_PIPE; } } else { std::unique_lock lock(pipe.m_mutex); - while (pipe.m_buffer.availableToRead() == 0 && pipe.m_alive) { + while (pipe.m_buffer.availableToRead() == 0 && pipe.m_open) { pipe.m_conditionWrite.notify_one(); pipe.m_conditionRead.wait(lock); } @@ -66,18 +66,18 @@ os::io::Library::v_size Pipe::Writer::write(const void *data, os::io::Library::v if(m_nonBlocking) { if(pipe.m_buffer.availableToWrite() > 0) { result = pipe.m_buffer.write(data, count); - } else if(pipe.m_alive) { + } else if(pipe.m_open) { result = oatpp::data::stream::Errors::ERROR_IO_WAIT_RETRY; } else { result = oatpp::data::stream::Errors::ERROR_IO_PIPE; } } else { std::unique_lock lock(pipe.m_mutex); - while (pipe.m_buffer.availableToWrite() == 0 && pipe.m_alive) { + while (pipe.m_buffer.availableToWrite() == 0 && pipe.m_open) { pipe.m_conditionRead.notify_one(); pipe.m_conditionWrite.wait(lock); } - if (pipe.m_alive && pipe.m_buffer.availableToWrite() > 0) { + if (pipe.m_open && pipe.m_buffer.availableToWrite() > 0) { result = pipe.m_buffer.write(data, count); } else { result = oatpp::data::stream::Errors::ERROR_IO_PIPE; diff --git a/network/virtual_/Pipe.hpp b/network/virtual_/Pipe.hpp index f81776f4..1785c97d 100644 --- a/network/virtual_/Pipe.hpp +++ b/network/virtual_/Pipe.hpp @@ -77,7 +77,7 @@ public: }; private: - bool m_alive; + bool m_open; Writer m_writer; Reader m_reader; oatpp::data::buffer::FIFOBuffer m_buffer; @@ -87,7 +87,7 @@ private: public: Pipe() - : m_alive(true) + : m_open(true) , m_writer(this) , m_reader(this) {} @@ -104,6 +104,10 @@ public: return &m_reader; } + void close() { + m_open = false; + } + }; }}} diff --git a/network/virtual_/Socket.hpp b/network/virtual_/Socket.hpp index 793e14b2..9acc2fd3 100644 --- a/network/virtual_/Socket.hpp +++ b/network/virtual_/Socket.hpp @@ -25,40 +25,42 @@ #ifndef oatpp_network_virtual__Socket_hpp #define oatpp_network_virtual__Socket_hpp -#include "Pipe.hpp" +#include "./Pipe.hpp" namespace oatpp { namespace network { namespace virtual_ { class Socket : public oatpp::base::Controllable, public oatpp::data::stream::IOStream { -public: - OBJECT_POOL(Socket_Pool, Socket, 32) - SHARED_OBJECT_POOL(Shared_Socket_Pool, Socket, 32) private: - std::shared_ptr m_pipeReader; - std::shared_ptr m_pipeWriter; + std::shared_ptr m_pipeIn; + std::shared_ptr m_pipeOut; +public: + Socket(const std::shared_ptr& pipeIn, const std::shared_ptr& pipeOut) + : m_pipeIn(pipeIn) + , m_pipeOut(pipeOut) + {} public: + static std::shared_ptr createShared(const std::shared_ptr& pipeIn, const std::shared_ptr& pipeOut) { + return std::make_shared(pipeIn, pipeOut); + } + + ~Socket() { + close(); + } + os::io::Library::v_size read(void *data, os::io::Library::v_size count) override { - if(m_pipeReader) { - return m_pipeReader->read(data, count); - } - return -1; + return m_pipeIn->getReader()->read(data, count); } os::io::Library::v_size write(const void *data, os::io::Library::v_size count) override { - if(m_pipeWriter) { - return m_pipeWriter->write(data, count); - } - return -1; - } - - bool isConnected() { - return m_pipeReader && m_pipeWriter; + return m_pipeOut->getWriter()->write(data, count); } void close() { - m_pipeReader.reset(); - m_pipeWriter.reset(); + m_pipeIn->close(); + m_pipeOut->close(); + m_pipeIn.reset(); + m_pipeOut.reset(); } }; diff --git a/test/network/virtual_/InterfaceTest.cpp b/test/network/virtual_/InterfaceTest.cpp new file mode 100644 index 00000000..5a91e7ac --- /dev/null +++ b/test/network/virtual_/InterfaceTest.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi, + * + * 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 "InterfaceTest.hpp" + +namespace oatpp { namespace test { namespace network { namespace virtual_ { + +namespace { + +} + +bool InterfaceTest::onRun() { + + return true; +} + +}}}} diff --git a/test/network/virtual_/InterfaceTest.hpp b/test/network/virtual_/InterfaceTest.hpp new file mode 100644 index 00000000..ef445f7b --- /dev/null +++ b/test/network/virtual_/InterfaceTest.hpp @@ -0,0 +1,40 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi, + * + * 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. + * + ***************************************************************************/ + +#ifndef oatpp_test_network_virtual__InterfaceTest_hpp +#define oatpp_test_network_virtual__InterfaceTest_hpp + +#include "oatpp/test/UnitTest.hpp" + +namespace oatpp { namespace test { namespace network { namespace virtual_ { + +class InterfaceTest : public UnitTest { +public: + InterfaceTest():UnitTest("TEST[network::virtual_::InterfaceTest]"){} + bool onRun() override; +}; + +}}}} + +#endif /* oatpp_test_network_virtual__InterfaceTest_hpp */ diff --git a/test/network/virtual_/PipeTest.cpp b/test/network/virtual_/PipeTest.cpp index 8286af54..35c024fe 100644 --- a/test/network/virtual_/PipeTest.cpp +++ b/test/network/virtual_/PipeTest.cpp @@ -131,8 +131,6 @@ namespace { } - - } bool PipeTest::onRun() {