diff --git a/include/FlameIDE/CMakeLists.txt b/include/FlameIDE/CMakeLists.txt index 2c05b3a4..44168890 100644 --- a/include/FlameIDE/CMakeLists.txt +++ b/include/FlameIDE/CMakeLists.txt @@ -8,6 +8,7 @@ set(HEADER_MODULES ${FLAME_INCLUDE_SUBMODLUES_PATH}/Common ${FLAME_INCLUDE_SUBMODLUES_PATH}/Constants ${FLAME_INCLUDE_SUBMODLUES_PATH}/Crypto + ${FLAME_INCLUDE_SUBMODLUES_PATH}/Handler ${FLAME_INCLUDE_SUBMODLUES_PATH}/Os ${FLAME_INCLUDE_SUBMODLUES_PATH}/Others # ${FLAME_INCLUDE_SUBMODLUES_PATH}/Streams diff --git a/include/FlameIDE/Common/Expected.hpp b/include/FlameIDE/Common/Expected.hpp index cb5388e3..d43bc0e4 100644 --- a/include/FlameIDE/Common/Expected.hpp +++ b/include/FlameIDE/Common/Expected.hpp @@ -36,11 +36,17 @@ class Expected template const Me &ifResult(Functor &&functor) const noexcept; + template + Me &ifResultGet(Functor &&functor) noexcept; + template Me &ifError(Functor &&functor) noexcept; template const Me &ifError(Functor &&functor) const noexcept; + template + Me &ifErrorGet(Functor &&functor) noexcept; + void done() noexcept; void done() const noexcept; @@ -52,7 +58,7 @@ class Expected { UNKNOWN = -1 , RESULT = 0 - , ERROR = 1 + , INVALID = 1 }; union Data @@ -146,10 +152,10 @@ Expected::operator=(Me &&expected) noexcept { expected.ifResult([this](ResultType &&result) { - operator=(move(result)); + this->operator=(move(result)); }).ifError([this](ErrorType &&error) { - operator=(move(error)); + this->operator=(move(error)); }).done(); return *this; } @@ -180,7 +186,7 @@ Expected::operator=(const ErrorType &error) noexcept { destroy(); flame_ide::placementNew(&data.error.value, error); - data.state = State::ERROR; + data.state = State::INVALID; return *this; } @@ -190,7 +196,7 @@ Expected::operator=(ErrorType &&error) noexcept { destroy(); flame_ide::placementNew(&data.error.value, move(error)); - data.state = State::ERROR; + data.state = State::INVALID; return *this; } @@ -221,12 +227,25 @@ Expected::ifResult(Functor &&functor) const noexcept return *this; } +template +template +Expected & +Expected::ifResultGet(Functor &&functor) noexcept +{ + if (State::RESULT != data.state) + return *this; + + functor(data.result.value); + + return *this; +} + template template Expected & Expected::ifError(Functor &&functor) noexcept { - if (State::ERROR != data.state) + if (State::INVALID != data.state) return *this; functor(move(data.error.value)); @@ -240,7 +259,20 @@ template const Expected & Expected::ifError(Functor &&functor) const noexcept { - if (State::ERROR != data.state) + if (State::INVALID != data.state) + return *this; + + functor(data.error.value); + + return *this; +} + +template +template +Expected & +Expected::ifErrorGet(Functor &&functor) noexcept +{ + if (State::INVALID != data.state) return *this; functor(data.error.value); @@ -267,7 +299,7 @@ void Expected::destroy() noexcept data.result.value.~ResultType(); return; - case State::ERROR: + case State::INVALID: data.error.value.~ErrorType(); return; diff --git a/include/FlameIDE/Common/PrimitiveTypes.hpp b/include/FlameIDE/Common/PrimitiveTypes.hpp index d7261745..7f29eb1c 100644 --- a/include/FlameIDE/Common/PrimitiveTypes.hpp +++ b/include/FlameIDE/Common/PrimitiveTypes.hpp @@ -23,7 +23,6 @@ using long_t = ::int64_t; using float_t = float; using double_t = double; using ldouble_t = long double; - using ptrint_t = ::intptr_t; using ptruint_t = ::uintptr_t; diff --git a/include/FlameIDE/Common/ReferenceWrapper.hpp b/include/FlameIDE/Common/ReferenceWrapper.hpp index 34269554..2fbe7774 100644 --- a/include/FlameIDE/Common/ReferenceWrapper.hpp +++ b/include/FlameIDE/Common/ReferenceWrapper.hpp @@ -13,9 +13,13 @@ template> class ReferenceWrapper { public: + using Me = ReferenceWrapper; using Pointer = typename Traits::Pointer; using Reference = typename Traits::Reference; + ReferenceWrapper(const Me &) noexcept = default; + ReferenceWrapper(Me &&) noexcept = default; + /// /// @brief ReferenceWrapper /// @param initValue @@ -28,6 +32,9 @@ class ReferenceWrapper /// ReferenceWrapper(Reference initValue) noexcept; + Me &operator=(const Me &) noexcept = default; + Me &operator=(Me &&) noexcept = default; + /// /// @brief get /// @return diff --git a/include/FlameIDE/Common/Traits/Functional.hpp b/include/FlameIDE/Common/Traits/Functional.hpp index 635df965..f81efc7b 100644 --- a/include/FlameIDE/Common/Traits/Functional.hpp +++ b/include/FlameIDE/Common/Traits/Functional.hpp @@ -342,6 +342,44 @@ struct DoSomeByIndex {} }; +/// +/// @brief The TypeMappingTrait class +/// @tparam T1 +/// @tparam T2 +/// +template +struct TypeMappingTrait +{ + using Type1 = T1; + using Type2 = T2; +}; + +/// +/// @brief The TypeMapper class +/// @tparam T +/// @tparam TypeMappingTrait +/// @tparam ENABLE_STATIC_ASSERT +/// +template +struct TypeMapper +{ + using Type = typename ChooseType< + ComparingTypes::VALUE + , typename TypeMappingTrait::Type2 + , typename ChooseType< + ComparingTypes::VALUE + , typename TypeMappingTrait::Type1 + , Empty + >::Type + >::Type; + + static_assert( + !ENABLE_STATIC_ASSERT + || ComparingTypes::VALUE == FalseType::VALUE + , "Type does not include in chosen TypeMatchingTrait" + ); +}; + } #endif // FLAMEIDE_COMMON_TRAITS_FUCTIONAL_HPP diff --git a/include/FlameIDE/Handler/CMakeLists.txt b/include/FlameIDE/Handler/CMakeLists.txt new file mode 100644 index 00000000..eda5ebe0 --- /dev/null +++ b/include/FlameIDE/Handler/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.14) + +set(SOURCE_MODULES + ${CMAKE_CURRENT_LIST_DIR}/Network +) +foreach(module ${SOURCE_MODULES}) + add_subdirectory(${module}) +endforeach() diff --git a/include/FlameIDE/Handler/Network/CMakeLists.txt b/include/FlameIDE/Handler/Network/CMakeLists.txt new file mode 100644 index 00000000..38a8684f --- /dev/null +++ b/include/FlameIDE/Handler/Network/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.14) + +set(NAME "Handler.Network") +set(NAME_ALIAS "Handler::Network") +set(LIBRARY_ALIAS_NAME ${FLAME_NAMESPACE}::${NAME_ALIAS}::Headers) +set(DEPENDENCY_LIST + ${FLAME_NAMESPACE}::Common::Headers + ${FLAME_NAMESPACE}::Os::Headers + ${FLAME_NAMESPACE}::Templates::Headers +) + +get_sources(FILE_LIST) +flame_header_library( + NAME "${NAME}" + LIBRARY_ALIAS_NAME "${LIBRARY_ALIAS_NAME}" + HEADER_LIST "${FILE_LIST}" + DEPENDENCY_TARGET_LIST "${DEPENDENCY_LIST}" + INCLUDE_PATHS "${FLAME_INCLUDE_PATH}" + INSTALL_SUBDIR "${FLAME_NAMESPACE}/${NAME}" +) diff --git a/include/FlameIDE/Handler/Network/Handler.hpp b/include/FlameIDE/Handler/Network/Handler.hpp new file mode 100644 index 00000000..f82a19a0 --- /dev/null +++ b/include/FlameIDE/Handler/Network/Handler.hpp @@ -0,0 +1,224 @@ +#ifndef FLAMEIDE_OS_NETWORK_HANDLER_HPP +#define FLAMEIDE_OS_NETWORK_HANDLER_HPP + +#include +#include + +#include +#include +#include + +namespace flame_ide +{namespace os +{namespace network +{ + +class UdpServer; +class UdpClient; + +class TcpServer; +class TcpClient; + +}}} // namespace flame_ide::os::network + +namespace flame_ide +{namespace handler +{namespace network +{ + +/// +/// @brief The Handler class +/// +class Handler +{ +public: + class Internal; + class Tcp; + class Udp; + +public: + class ServerHandle; + class SessionHandle; + + using ExpectedServerHandle = Expected; + using ExpectedSessionHandle = Expected; + + using ExpectedUdpServer = Expected; + using ExpectedUdpClient = Expected; + + using ExpectedTcpServer = Expected; + using ExpectedTcpClient = Expected; + +public: + Handler() noexcept; + Handler(const Handler &) noexcept = delete; + Handler(Handler &&handler) noexcept; + ~Handler() noexcept; + + Handler &operator=(const Handler &) noexcept = delete; + Handler &operator=(Handler &&handler) noexcept; + + /// @brief pushUdp + /// @param server + /// @return + ExpectedServerHandle pushUdp(os::network::UdpServer &&server) noexcept; + + /// @brief pushUdp + /// @param client + /// @return + ExpectedSessionHandle pushUdp(os::network::UdpClient &&client) noexcept; + + /// @brief pushTcp + /// @param server + /// @return + ExpectedServerHandle pushTcp(os::network::TcpServer &&server) noexcept; + + /// @brief pushTcp + /// @param client + /// @return + ExpectedSessionHandle pushTcp(os::network::TcpClient &&client) noexcept; + + /// @brief pop + /// @param server + /// @return + ExpectedUdpServer popUdp(ServerHandle &handle) noexcept; + + /// @brief pop + /// @param client + /// @return + ExpectedUdpClient popUdp(SessionHandle &handle) noexcept; + + /// @brief pop + /// @param server + /// @return + ExpectedTcpServer popTcp(ServerHandle &handle) noexcept; + + /// @brief pop + /// @param client + /// @return + ExpectedTcpClient popTcp(SessionHandle &handle) noexcept; + + /// @brief start + /// @return + os::Status start() noexcept; + + /// @brief stop + /// @return + os::Status stop() noexcept; + +private: + Internal *internal = nullptr; +}; + +}}} // namespace flame_ide::handler::network + +// Handler::ServerHandle +namespace flame_ide +{namespace handler +{namespace network +{ + +class Handler::ServerHandle +{ +public: + ServerHandle() noexcept = default; + ServerHandle(ServerHandle &&) noexcept = default; + ~ServerHandle() noexcept; + + ServerHandle &operator=(ServerHandle &&) noexcept = default; + + explicit operator bool() const noexcept; + + /// + /// @brief getSessionHandle + /// @return + /// + Handler::ExpectedSessionHandle getSessionHandle() noexcept; + +private: + friend class Handler; + friend class Handler::Udp; + friend class Handler::Tcp; + +private: + static constexpr Types::size_t OBJECT_SIZE = 16; + + using Object = ::flame_ide::templates::Object; + using CallbackGetSessionHandle = Handler::ExpectedSessionHandle (*)(Object &); + using CallbackDeregistrate = void (*)(Handler::ServerHandle *); + +private: + // void *data = nullptr; + + Object object; + CallbackGetSessionHandle callbackGetSessionHandle = nullptr; + CallbackDeregistrate callbackDeregistrate = nullptr; +}; + +}}} // namespace flame_ide::handler::network + +// Handler::SessionHandle +namespace flame_ide +{namespace handler +{namespace network +{ + +class Handler::SessionHandle +{ +public: + SessionHandle() noexcept = default; + SessionHandle(SessionHandle &&) noexcept = default; + ~SessionHandle() noexcept; + + SessionHandle &operator=(SessionHandle &&) noexcept = default; + + explicit operator bool() const noexcept; + + /// + /// @brief bytesToRead + /// @return + /// + Types::ssize_t bytesToRead() const noexcept; + + /// + /// @brief receive + /// @return + /// + Types::ssize_t receive(flame_ide::templates::Range) noexcept; + + /// + /// @brief send + /// @return + /// + Types::ssize_t send(flame_ide::templates::Range) noexcept; + +private: + friend class Handler; + friend class Handler::Udp; + friend class Handler::Tcp; + friend class Handler::ServerHandle; + +private: + static constexpr Types::size_t OBJECT_SIZE = 64; + + using Object = ::flame_ide::templates::Object; + using CallbackBytesToRead = ::flame_ide::Types::ssize_t (*)(const Object &); + using CallbackReceive = ::flame_ide::Types::ssize_t (*)( + Object &, ::flame_ide::templates::Range + ); + using CallbackSend = ::flame_ide::Types::ssize_t (*)( + Object &, ::flame_ide::templates::Range + ); + using CallbackDeregistrate = void (*)(Handler::SessionHandle *); + +private: + Object object; + CallbackBytesToRead callbackBytesToRead = nullptr; + CallbackReceive callbackReceive = nullptr; + CallbackSend callbackSend = nullptr; + CallbackDeregistrate callbackDeregistrate = nullptr; +}; + +}}} // namespace flame_ide::handler::network + +#endif // FLAMEIDE_OS_NETWORK_HANDLER_HPP diff --git a/include/FlameIDE/Handler/Network/Headers.cmake b/include/FlameIDE/Handler/Network/Headers.cmake new file mode 100644 index 00000000..ac4c9f15 --- /dev/null +++ b/include/FlameIDE/Handler/Network/Headers.cmake @@ -0,0 +1,3 @@ +set (HEADER_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/Handler.hpp +) diff --git a/include/FlameIDE/Os/Async/Network/NotificatorBase.hpp b/include/FlameIDE/Os/Async/Network/NotificatorBase.hpp index dbf9961b..e716caa5 100644 --- a/include/FlameIDE/Os/Async/Network/NotificatorBase.hpp +++ b/include/FlameIDE/Os/Async/Network/NotificatorBase.hpp @@ -9,7 +9,25 @@ namespace flame_ide {namespace network { -using NotificatorBase = flame_ide::FunctorConstBase; +namespace tag +{ + +struct UdpServer {}; +struct UdpClient {}; +struct TcpServer {}; +struct TcpAcceptedConnection {}; +struct TcpClient {}; + +} // namespace tag + +template +class NotificatorBase: public flame_ide::DefaultFunctorBase {}; + +using UdpServerNotificatorBase = NotificatorBase; +using UdpClientNotificatorBase = NotificatorBase; +using TcpServerNotificatorBase = NotificatorBase; +using TcpAcceptedConnectionNotificatorBase = NotificatorBase; +using TcpClientNotificatorBase = NotificatorBase; }}}} // namespace flame_ide::os::async::network diff --git a/include/FlameIDE/Os/Async/Network/Registrar.hpp b/include/FlameIDE/Os/Async/Network/Registrar.hpp index e377592c..4eede700 100644 --- a/include/FlameIDE/Os/Async/Network/Registrar.hpp +++ b/include/FlameIDE/Os/Async/Network/Registrar.hpp @@ -4,7 +4,6 @@ #include #include #include -#include namespace flame_ide {namespace os @@ -24,7 +23,18 @@ namespace flame_ide {namespace network { -struct Config +enum class EventType: Types::int_t +{ + INVALID = -1 + , INIT = 0 + , READ + , WRITE + , READ_WRITE + , CLOSE +}; + + +struct SocketsInfo { struct Info { @@ -35,9 +45,17 @@ struct Config Types::size_t tcpClients; }; - Info max; - Info current; + const Info max; + const Info current; +}; + +struct AsyncEvent +{ + os::SocketDescriptor descriptor = os::SOCKET_INVALID.descriptor; + EventType event = EventType::INVALID; }; +bool operator==(const AsyncEvent &ae1, const AsyncEvent &ae2) noexcept; +bool operator!=(const AsyncEvent &ae1, const AsyncEvent &ae2) noexcept; class Registrar { @@ -51,7 +69,7 @@ class Registrar Registrar &operator=(Registrar &&) noexcept = default; public: - const Config &getConfig() const noexcept; + SocketsInfo getInfo() const noexcept; public: os::Status add(const os::network::UdpServer &socket) noexcept; @@ -66,20 +84,19 @@ class Registrar os::Status remove(const os::network::TcpServer::WithClient &socket) noexcept; os::Status remove(const os::network::TcpClient &socket) noexcept; - os::SocketDescriptor popUdpServer() noexcept; - os::SocketDescriptor popUdpClient() noexcept; + AsyncEvent popUdpServer() noexcept; + AsyncEvent popUdpClient() noexcept; AcceptedConnection popTcpServerAcception() noexcept; - os::SocketDescriptor popTcpServer() noexcept; - os::SocketDescriptor popTcpClient() noexcept; + AsyncEvent popTcpServer() noexcept; + AsyncEvent popTcpClient() noexcept; - bool pushUdpServer(os::SocketDescriptor socket) noexcept; - bool pushUdpClient(os::SocketDescriptor socket) noexcept; - bool pushTcpServerAcception(AcceptedConnection connection) noexcept; - bool pushTcpServer(os::SocketDescriptor socket) noexcept; - bool pushTcpClient(os::SocketDescriptor socket) noexcept; + void setNotificator(UdpServerNotificatorBase ¬ificator) noexcept; + void setNotificator(UdpClientNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpServerNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpAcceptedConnectionNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpClientNotificatorBase ¬ificator) noexcept; - void setNotificator(const NotificatorBase ¬ificator) noexcept; - void unsetNotificator() noexcept; + void unsetNotificators() noexcept; void clear() noexcept; }; diff --git a/include/FlameIDE/Os/Network/NetworkBase.hpp b/include/FlameIDE/Os/Network/NetworkBase.hpp index 7b5c5ecc..5c9fb20c 100644 --- a/include/FlameIDE/Os/Network/NetworkBase.hpp +++ b/include/FlameIDE/Os/Network/NetworkBase.hpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -38,6 +39,7 @@ class NetworkBase: public NonCopy static const NativeCallbacks &callbacks() noexcept; protected: + NetworkBase() noexcept = default; NetworkBase(Socket socket) noexcept; NetworkBase(NetworkBase &&base) noexcept; @@ -54,10 +56,10 @@ class NetworkBase: public NonCopy static Types::int_t checkStatus(Status status) noexcept; protected: - Socket socket; + Socket socket = SOCKET_INVALID; private: - Status status = 0; + Status status = STATUS_SUCCESS; }; }}} // namespace flame_ide::os::network diff --git a/include/FlameIDE/Os/Network/TcpClient.hpp b/include/FlameIDE/Os/Network/TcpClient.hpp index 76a0cb59..1c0d74a9 100644 --- a/include/FlameIDE/Os/Network/TcpClient.hpp +++ b/include/FlameIDE/Os/Network/TcpClient.hpp @@ -18,7 +18,8 @@ class TcpClient final: public NetworkBase struct NativeCallbacks; public: - TcpClient() noexcept = delete; + TcpClient() noexcept : NetworkBase() {} + TcpClient(const TcpClient &) noexcept = delete; TcpClient(TcpClient &&client) noexcept; diff --git a/include/FlameIDE/Os/Network/TcpServer.hpp b/include/FlameIDE/Os/Network/TcpServer.hpp index f8f8a641..ef792e0d 100644 --- a/include/FlameIDE/Os/Network/TcpServer.hpp +++ b/include/FlameIDE/Os/Network/TcpServer.hpp @@ -21,7 +21,7 @@ class TcpServer final: public NetworkBase struct NativeCallbacks; public: - TcpServer() noexcept = delete; + TcpServer() noexcept : NetworkBase() {} TcpServer(const TcpServer &tcpServer) noexcept = delete; TcpServer(TcpServer &&tcpServer) noexcept; diff --git a/include/FlameIDE/Os/Network/UdpClient.hpp b/include/FlameIDE/Os/Network/UdpClient.hpp index 48874c9a..e2c4ba51 100644 --- a/include/FlameIDE/Os/Network/UdpClient.hpp +++ b/include/FlameIDE/Os/Network/UdpClient.hpp @@ -18,6 +18,8 @@ class UdpClient final: public NetworkBase struct NativeCallbacks; public: + UdpClient() noexcept : NetworkBase() {} + UdpClient(UdpClient &&udpClient) noexcept; UdpClient(Ipv4 ip) noexcept; diff --git a/include/FlameIDE/Os/Network/UdpServer.hpp b/include/FlameIDE/Os/Network/UdpServer.hpp index 6f83ac9d..de030e5b 100644 --- a/include/FlameIDE/Os/Network/UdpServer.hpp +++ b/include/FlameIDE/Os/Network/UdpServer.hpp @@ -19,6 +19,8 @@ class UdpServer final: public NetworkBase struct NativeCallbacks; public: + UdpServer() noexcept : NetworkBase() {} + UdpServer(UdpServer &&udpServer) noexcept; UdpServer(Ipv4::Port port) noexcept; ~UdpServer() noexcept = default; diff --git a/include/FlameIDE/Os/Threads/ConditionVariable.hpp b/include/FlameIDE/Os/Threads/ConditionVariable.hpp index 58e97671..7115692e 100644 --- a/include/FlameIDE/Os/Threads/ConditionVariable.hpp +++ b/include/FlameIDE/Os/Threads/ConditionVariable.hpp @@ -40,16 +40,6 @@ class ConditionVariable template void wait(Functor &&functor) noexcept; - /// - /// @brief Trying wait for signal - /// - bool tryWait() noexcept; - - /// - /// @brief Disable waiting (decrement counter) - /// - void unwait() noexcept; - /// /// @brief isWait /// @return @@ -62,7 +52,7 @@ class ConditionVariable void notify() noexcept; private: - Counter counter; + Counter counter; UniqueLocker locker; }; @@ -75,14 +65,14 @@ namespace flame_ide template ConditionVariable::ConditionVariable(LockObject &lock) noexcept : - locker{ lock, UniqueLocker::LOCK } + counter{ decltype(counter.current()){ 0 } }, locker{ lock, UniqueLocker::LOCK } {} template void ConditionVariable::wait(Functor &&functor) noexcept { static_assert( - CompareTypesResult + ComparingTypes::VALUE , "Return type of input fuctior must be boolean" ); diff --git a/include/FlameIDE/Os/Threads/Counter.hpp b/include/FlameIDE/Os/Threads/Counter.hpp index 5a3bf480..9491a0e0 100644 --- a/include/FlameIDE/Os/Threads/Counter.hpp +++ b/include/FlameIDE/Os/Threads/Counter.hpp @@ -8,16 +8,20 @@ namespace flame_ide {namespace threads { -template +template class Counter { public: - using Me = Counter; + using Me = Counter; + using Lock = LockType; + using Value = ValueType; Counter() noexcept = default; Counter(const Me &) noexcept = delete; Counter(Me &&) noexcept = default; + Counter(Value initValue) noexcept; + ~Counter() noexcept = default; Me &operator=(const Me &) noexcept = delete; @@ -40,24 +44,31 @@ namespace flame_ide {namespace threads { -template -Counter &Counter::operator++() noexcept +template +Counter::Counter( + Counter::Value initValue +) noexcept : value{ initValue } +{} + +template +Counter &Counter::operator++() noexcept { Locker locker{ lock }; ++value; return *this; } -template -Counter &Counter::operator--() noexcept +template +Counter &Counter::operator--() noexcept { Locker locker{ lock }; --value; return *this; } -template -Value Counter::current() const noexcept +template +typename Counter::Value +Counter::current() const noexcept { Locker locker{ lock }; return value; diff --git a/include/FlameIDE/Templates/Array.hpp b/include/FlameIDE/Templates/Array.hpp index a1e73ae7..61e8470f 100644 --- a/include/FlameIDE/Templates/Array.hpp +++ b/include/FlameIDE/Templates/Array.hpp @@ -1323,7 +1323,7 @@ TEMPLATE_DEFINE ARRAY_TYPE::Array(ARRAY_TYPE &&array) noexcept { auto it = this->begin(); - for (MoveReference i : array) + for (auto &&i : array) { *it = move(i); ++it; diff --git a/include/FlameIDE/Templates/HybridVector.hpp b/include/FlameIDE/Templates/HybridVector.hpp index 04af186a..7883769e 100644 --- a/include/FlameIDE/Templates/HybridVector.hpp +++ b/include/FlameIDE/Templates/HybridVector.hpp @@ -827,8 +827,8 @@ bool ITERATOR_TYPE::operator!=(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator<(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -853,8 +853,8 @@ bool ITERATOR_TYPE::operator<(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator>(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -879,8 +879,8 @@ bool ITERATOR_TYPE::operator>(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator<=(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -905,8 +905,8 @@ bool ITERATOR_TYPE::operator<=(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator>=(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -1167,8 +1167,8 @@ bool ITERATOR_TYPE::operator!=(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator<(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -1196,8 +1196,8 @@ bool ITERATOR_TYPE::operator<(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator>(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -1226,8 +1226,8 @@ bool ITERATOR_TYPE::operator>(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator<=(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { @@ -1256,8 +1256,8 @@ bool ITERATOR_TYPE::operator<=(const Me &iterator) const ITERATOR_TEMPLATE bool ITERATOR_TYPE::operator>=(const Me &iterator) const { - if (wrappedIterator.template getCurrentIndex() == - iterator.wrappedIterator.template getCurrentIndex()) + if (wrappedIterator.getCurrentIndex() == + iterator.wrappedIterator.getCurrentIndex()) { if (isArrayIterator()) { diff --git a/include/FlameIDE/Templates/Object.hpp b/include/FlameIDE/Templates/Object.hpp index 22c4d680..92309a3e 100644 --- a/include/FlameIDE/Templates/Object.hpp +++ b/include/FlameIDE/Templates/Object.hpp @@ -206,7 +206,7 @@ template flame_ide::AddMoveReferenceType Object::move() noexcept { callbackDestroy = nullptr; - return flame_ide::move(get()); + return flame_ide::move(get()); } template diff --git a/include/FlameIDE/Templates/Optional.hpp b/include/FlameIDE/Templates/Optional.hpp index 3b17ea2e..77ef27a6 100644 --- a/include/FlameIDE/Templates/Optional.hpp +++ b/include/FlameIDE/Templates/Optional.hpp @@ -45,6 +45,7 @@ class Optional typename Me::Reference get(); typename Me::ConstReference get() const; + typename Me::MoveReference pull() noexcept; typename Me::Pointer getPointer(); typename Me::PointerToConst getPointer() const; @@ -55,7 +56,7 @@ class Optional typename Me::Pointer toValue(); typename Me::PointerToConst toValue() const; - AlignObject value; + AlignObject object; bool isFill; }; @@ -66,7 +67,7 @@ namespace flame_ide { template -Optional::Optional() noexcept : value(), isFill(false) +Optional::Optional() noexcept : object(), isFill(false) {} template @@ -243,6 +244,13 @@ typename Optional::ConstReference Optional::get() const return *toValue(); } +template +typename Optional::MoveReference Optional::pull() noexcept +{ + isFill = false; + return flame_ide::move(get()); +} + template typename Optional::Pointer Optional::getPointer() { @@ -269,7 +277,7 @@ template typename Optional::Pointer Optional::toValue() { return static_cast( - static_cast(value.array) + static_cast(object.array) ); } @@ -277,7 +285,7 @@ template typename Optional::PointerToConst Optional::toValue() const { return static_cast( - static_cast(value.array) + static_cast(object.array) ); } diff --git a/include/FlameIDE/Templates/SimpleAlgorithms.hpp b/include/FlameIDE/Templates/SimpleAlgorithms.hpp index bc34429f..d0171737 100644 --- a/include/FlameIDE/Templates/SimpleAlgorithms.hpp +++ b/include/FlameIDE/Templates/SimpleAlgorithms.hpp @@ -57,7 +57,7 @@ void foreachChangable(InputContainer &container, FuncObject &&func); template void foreachChangable(Range &range, FuncObject &&func); -}} +}} // namespace flame_ide::templates namespace flame_ide {namespace templates @@ -115,7 +115,7 @@ void foreach(IteratorInput start, IteratorInput end, FuncObject &&func) } template -void foreach(const InputContainer& container, FuncObject func) +void foreach(const InputContainer& container, FuncObject &&func) { foreach(container.begin(), container.end(), func); } @@ -138,6 +138,6 @@ void foreachChangable(Range &range, FuncObject &&func) foreach(range.begin(), range.end(), func); } -}} +}} // namespace flame_ide::templates #endif // SIMPLEALGORITHMS_HPP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a6842898..74f16177 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCE_MODULES ${FLAME_SOURCE_SUBMODLUES_PATH}/Bus ${FLAME_SOURCE_SUBMODLUES_PATH}/Common ${FLAME_SOURCE_SUBMODLUES_PATH}/Crypto + ${FLAME_SOURCE_SUBMODLUES_PATH}/Handler ${FLAME_SOURCE_SUBMODLUES_PATH}/Os # ${FLAME_SOURCE_SUBMODLUES_PATH}/Streams ${FLAME_SOURCE_SUBMODLUES_PATH}/Ubjson diff --git a/src/Common/Tests/FunctionalTraitTest.cpp b/src/Common/Tests/FunctionalTraitTest.cpp new file mode 100644 index 00000000..ea7934e0 --- /dev/null +++ b/src/Common/Tests/FunctionalTraitTest.cpp @@ -0,0 +1,47 @@ +#include + +#include + +namespace flame_ide +{namespace common +{namespace tests +{ + +FunctionalTraitTest::FunctionalTraitTest() noexcept : ::AbstractTest{ "FunctionalTrait" } +{} + +FunctionalTraitTest::~FunctionalTraitTest() noexcept = default; + +int FunctionalTraitTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "TypeMapper" + , [this] { return typeMapper(); } + )); + return ResultType::SUCCESS; +} + +int FunctionalTraitTest::typeMapper() +{ + using T1 = long long; + using T2 = unsigned long long; + using T3 = double; + using TestTypeMatchingTrait = TypeMappingTrait; + + using T2Result = TypeMapper::Type; + using T1Result = TypeMapper::Type; + // using T3Result = TypeMapper::Type; // static assert + using T3Result = TypeMapper::Type; + + bool t1ComparationResult = ComparingTypes::VALUE; + bool t2ComparationResult = ComparingTypes::VALUE; + bool t3ComparationResult = ComparingTypes::VALUE; + + IN_CASE_CHECK(t1ComparationResult == true); + IN_CASE_CHECK(t2ComparationResult == true); + IN_CASE_CHECK(t3ComparationResult == true); + + return ResultType::SUCCESS; +} + +}}} // namespace flame_ide::common::tests diff --git a/src/Common/Tests/FunctionalTraitTest.hpp b/src/Common/Tests/FunctionalTraitTest.hpp new file mode 100644 index 00000000..02efde71 --- /dev/null +++ b/src/Common/Tests/FunctionalTraitTest.hpp @@ -0,0 +1,26 @@ +#ifndef FLAMEIDE_COMMON_TESTS_FUNCTIONALTRAITTEST_HPP +#define FLAMEIDE_COMMON_TESTS_FUNCTIONALTRAITTEST_HPP + +#include + +namespace flame_ide +{namespace common +{namespace tests +{ + +class FunctionalTraitTest: public ::AbstractTest +{ +public: + FunctionalTraitTest() noexcept; + ~FunctionalTraitTest() noexcept override; + +private: + int vStart() override; + +private: + int typeMapper(); +}; + +}}} // namespace flame_ide::common::tests + +#endif // FLAMEIDE_COMMON_TESTS_FUNCTIONALTRAITTEST_HPP diff --git a/src/Common/Tests/Sources.cmake b/src/Common/Tests/Sources.cmake index 3e585535..1c26f64a 100644 --- a/src/Common/Tests/Sources.cmake +++ b/src/Common/Tests/Sources.cmake @@ -1,6 +1,8 @@ set (SOURCE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/ExpectedTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ExpectedTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/FunctionalTraitTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/FunctionalTraitTest.hpp ${CMAKE_CURRENT_SOURCE_DIR}/TestAggregator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TestAggregator.hpp ${CMAKE_CURRENT_SOURCE_DIR}/UtilsTest.cpp diff --git a/src/Common/Tests/TestAggregator.cpp b/src/Common/Tests/TestAggregator.cpp index eef69d18..6d36a9f9 100644 --- a/src/Common/Tests/TestAggregator.cpp +++ b/src/Common/Tests/TestAggregator.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -14,6 +15,7 @@ TestAggregator::TestAggregator() : ::TestAggregator("Common") pushBackTest(std::make_shared()); pushBackTest(std::make_shared()); pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); } }}} // namespace flame_ide::common::tests diff --git a/src/Common/Tests/VoidTypeTest.cpp b/src/Common/Tests/VoidTypeTest.cpp index 8a5ccfc9..7310d72d 100644 --- a/src/Common/Tests/VoidTypeTest.cpp +++ b/src/Common/Tests/VoidTypeTest.cpp @@ -28,8 +28,14 @@ VoidTypeTest::~VoidTypeTest() = default; int VoidTypeTest::vStart() { - IN_CASE_CHECK(HasMemember::VALUE == TrueType::VALUE); - IN_CASE_CHECK_END(HasMemember::VALUE == FalseType::VALUE); + bool isExistMemberStructContainMember = ( + HasMemember::VALUE == true + ); + bool isNotExistMemberStructContainMember = ( + HasMemember::VALUE == false + ); + IN_CASE_CHECK(isExistMemberStructContainMember); + IN_CASE_CHECK_END(isNotExistMemberStructContainMember); } }}} // flame_ide::common::tests diff --git a/src/Handler/CMakeLists.txt b/src/Handler/CMakeLists.txt new file mode 100644 index 00000000..eda5ebe0 --- /dev/null +++ b/src/Handler/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.14) + +set(SOURCE_MODULES + ${CMAKE_CURRENT_LIST_DIR}/Network +) +foreach(module ${SOURCE_MODULES}) + add_subdirectory(${module}) +endforeach() diff --git a/src/Handler/Network/CMakeLists.txt b/src/Handler/Network/CMakeLists.txt new file mode 100644 index 00000000..765598f1 --- /dev/null +++ b/src/Handler/Network/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.14) + +set(NAME Handler.Network) +set(NAME_ALIAS Handler::Network) +set(INCLUDE_PATHS ${FLAME_INCLUDE_PATH}) + +set(DEPENDENCY_HEADER_TARGETS + ${FLAME_NAMESPACE}::Handler::Network::Headers +) +set(DEPENDENCY_TARGETS_FOR_STATIC + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Udp::Object" + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Tcp::Object" + "${FLAME_NAMESPACE}::Os::Static" +) +set(DEPENDENCY_TARGETS_FOR_SHARED + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Udp::Object::Independ" + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Tcp::Object::Independ" + "${FLAME_NAMESPACE}::Os::Shared" +) + +if(FLAME_MAKE_STATIC) + set(MAKE_STATIC MAKE_STATIC) +endif() +if(FLAME_MAKE_SHARED) + set(MAKE_SHARED MAKE_SHARED) +endif() + +get_sources(FILE_LIST) +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${GENERATED_INCLUDE_PATH}" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + DEPENDENCY_TARGETS_FOR_STATIC "${DEPENDENCY_TARGETS_FOR_STATIC}" + DEPENDENCY_TARGETS_FOR_SHARED "${DEPENDENCY_TARGETS_FOR_SHARED}" + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + STATIC_ALIAS_NAME "${FLAME_NAMESPACE}::${NAME_ALIAS}::Static" + SHARED_ALIAS_NAME "${FLAME_NAMESPACE}::${NAME_ALIAS}::Shared" + + NO_RTTI + NO_EXCEPTIONS + + ${MAKE_STATIC} + ${MAKE_SHARED} +) + +set(SOURCE_MODULES + ${CMAKE_CURRENT_LIST_DIR}/Udp + ${CMAKE_CURRENT_LIST_DIR}/Tcp +) +foreach(module ${SOURCE_MODULES}) + add_subdirectory(${module}) +endforeach() diff --git a/src/Handler/Network/Config.cmake b/src/Handler/Network/Config.cmake new file mode 100644 index 00000000..515b4a76 --- /dev/null +++ b/src/Handler/Network/Config.cmake @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.14) + +# Udp + +set(UDP_MESSAGE_SIZE_KB 32) + +set(UDP_SERVERS 8) +set(UDP_SERVER_INPUT_QUEUE_SIZE 32) +set(UDP_SERVER_OUTPUT_QUEUE_SIZE 32) + +set(UDP_CLIENTS 16) +set(UDP_CLIENT_INPUT_QUEUE_SIZE 32) +set(UDP_CLIENT_OUTPUT_QUEUE_SIZE 32) + +# Tcp + +set(TCP_SERVERS 8) +set(TCP_SERVER_INPUT_BUFFER_KB 64) +set(TCP_SERVER_OUTPUT_BUFFER_KB 64) + +set(TCP_CLIENTS 16) +set(TCP_CLIENT_INPUT_BUFFER_KB 64) +set(TCP_CLIENT_OUTPUT_BUFFER_KB 64) + +# Common + +set(NUMBER_OF_WORKERS 2) + +# Add defines + +set(HANDLER_NETWORK_DEFINES + "HANDLER_NETWORK_UDP_SERVERS=${UDP_SERVERS}" + "HANDLER_NETWORK_UDP_CLIENTS=${UDP_CLIENTS}" + "HANDLER_NETWORK_UDP_MESSAGE_SIZE_KB=${UDP_MESSAGE_SIZE_KB}" + "HANDLER_NETWORK_UDP_SERVER_INPUT_QUEUE_SIZE=${UDP_SERVER_INPUT_QUEUE_SIZE}" + "HANDLER_NETWORK_UDP_SERVER_OUTPUT_QUEUE_SIZE=${UDP_SERVER_OUTPUT_QUEUE_SIZE}" + "HANDLER_NETWORK_UDP_CLIENT_INPUT_QUEUE_SIZE=${UDP_CLIENT_INPUT_QUEUE_SIZE}" + "HANDLER_NETWORK_UDP_CLIENT_OUTPUT_QUEUE_SIZE=${UDP_CLIENT_OUTPUT_QUEUE_SIZE}" + + "HANDLER_NETWORK_TCP_SERVERS=${TCP_SERVERS}" + "HANDLER_NETWORK_TCP_CLIENTS=${TCP_CLIENTS}" + "HANDLER_NETWORK_TCP_SERVER_INPUT_BUFFER_KB=${TCP_SERVER_INPUT_BUFFER_KB}" + "HANDLER_NETWORK_TCP_SERVER_OUTPUT_BUFFER_KB=${TCP_SERVER_OUTPUT_BUFFER_KB}" + "HANDLER_NETWORK_TCP_CLIENT_INPUT_BUFFER_KB=${TCP_CLIENT_INPUT_BUFFER_KB}" + "HANDLER_NETWORK_TCP_CLIENT_OUTPUT_BUFFER_KB=${TCP_CLIENT_OUTPUT_BUFFER_KB}" + + "HANDLER_NETWORK_NUMBER_OF_WORKERS=${NUMBER_OF_WORKERS}" +) diff --git a/src/Handler/Network/Functions.hpp b/src/Handler/Network/Functions.hpp new file mode 100644 index 00000000..e30b7f25 --- /dev/null +++ b/src/Handler/Network/Functions.hpp @@ -0,0 +1,65 @@ +#ifndef HANDLER_INTERNAL_FUNCTIONS_HPP +#define HANDLER_INTERNAL_FUNCTIONS_HPP + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +template +inline bool initPointer(Pointer &pointer, os::threads::Spin &spin) noexcept +{ + os::threads::Locker lock{ spin }; + if (!pointer) + pointer = Pointer{}; + return pointer; +} + +template +inline auto *pushData(Pointer &pointer, os::threads::Spin &spin + , LambdaCheck &&check, LambdaAssign &&assignTo) noexcept +{ + using DataPointer = flame_ide::RemoveAllTypebegin())>; + using Data = flame_ide::RemoveAllTypebegin()))>; + + os::threads::Locker lock{ spin }; + Data *data = nullptr; + for (DataPointer &i : *pointer) + { + if (check(*i)) + continue; + + data = i.pointer(); + break; + } + assignTo(*data); + return data; +} + +template< + typename Pointer, typename Data, typename LambdaCheck + , typename LambdaReturn +> +inline auto popData(Pointer &pointer, os::threads::Spin &spin, Data &data + , LambdaCheck &&check, LambdaReturn &&returnData) noexcept +{ + using DataPointer = flame_ide::RemoveAllTypebegin())>; + using ReturnData = decltype(returnData(*data)); + + os::threads::Locker lock{ spin }; + for (DataPointer &i : *pointer) + { + if (!check(*data, *i)) + continue; + + return returnData(*i); + } + return ReturnData{}; +} + +}}} // namespace flame_ide::handler::network + +#endif // HANDLER_INTERNAL_FUNCTIONS_HPP diff --git a/src/Handler/Network/Handler.cpp b/src/Handler/Network/Handler.cpp new file mode 100644 index 00000000..f6ea8905 --- /dev/null +++ b/src/Handler/Network/Handler.cpp @@ -0,0 +1,178 @@ +#include + +#include + +#include + +// private functions +namespace flame_ide +{namespace handler +{namespace network +{ +namespace // anonymous +{ + +Handler::Internal *makeInternal() noexcept; +void destroyInternal(Handler::Internal *&internal) noexcept; + +} // namespace anonymous +}}} // namespace flame_ide::handler::network + +// Handler +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::Handler() noexcept : internal{ makeInternal() } +{} + +Handler::Handler(Handler &&handler) noexcept +{ + operator=(flame_ide::move(handler)); +} + +Handler::~Handler() noexcept +{ + stop(); + + if (!internal) + return; + + destroyInternal(internal); +} + +Handler &Handler::operator=(Handler &&handler) noexcept +{ + internal = handler.internal; + handler.internal = nullptr; + + return *this; +} + +Handler::ExpectedServerHandle Handler::pushUdp(os::network::UdpServer &&server) noexcept +{ + auto result = internal->udp().push(flame_ide::move(server)); + result.ifResultGet( + [this](ServerHandle &result) + { + auto &handleData = result.object.get(); + const auto &endpoint = handleData.server->endpoint().get(); + const auto status = os::async::network::Registrar{}.add(endpoint); + flame_ide::unused(status); + + handleData.handler = this; + result.callbackDeregistrate = + internal->udp().serverCallbackDeregistrate(); + } + ); + return flame_ide::move(result); +} + +Handler::ExpectedSessionHandle Handler::pushUdp(os::network::UdpClient &&client) noexcept +{ + auto result = internal->udp().push(flame_ide::move(client)); + result.ifResultGet( + [this](SessionHandle &result) + { + auto &handleData = result.object.get(); + const auto &endpoint = handleData.data.client->endpoint().get(); + const auto status = os::async::network::Registrar{}.add(endpoint); + flame_ide::unused(status); + + handleData.handler = this; + result.callbackDeregistrate = + internal->udp().clientCallbackDeregistrate(); + } + ); + + return flame_ide::move(result); +} + +Handler::ExpectedServerHandle Handler::pushTcp(os::network::TcpServer &&server) noexcept +{ + auto result = internal->tcp().push(flame_ide::move(server)); + // const decltype(result) &constResult = result; + // constResult.ifResult( + // [this](const auto &result) + // { + // const auto &endpoint = *static_cast( + // result.data + // ); + // internal->registrar().add(endpoint); + // } + // ); + return flame_ide::move(result); +} + +Handler::ExpectedSessionHandle Handler::pushTcp(os::network::TcpClient &&client) noexcept +{ + auto result = internal->tcp().push(flame_ide::move(client)); + const decltype(result) &constResult = result; + constResult.ifResult( + [](const auto &) + { + // TODO + // const auto &endpoint = result.object.get() + // .client->endpoint().get(); + // internal->registrar().add(endpoint); + } + ); + + return result; +} + +Handler::ExpectedUdpServer Handler::popUdp(ServerHandle &handle) noexcept +{ + return internal->udp().pop(handle); +} + +Handler::ExpectedUdpClient Handler::popUdp(SessionHandle &handle) noexcept +{ + return internal->udp().pop(handle); +} + +Handler::ExpectedTcpServer Handler::popTcp(ServerHandle &handle) noexcept +{ + return internal->tcp().pop(handle); +} + +Handler::ExpectedTcpClient Handler::popTcp(SessionHandle &handle) noexcept +{ + return internal->tcp().pop(handle); +} + +os::Status Handler::start() noexcept +{ + return internal->start(); +} + +os::Status Handler::stop() noexcept +{ + return internal->stop(); +} + +}}} // namespace flame_ide::handler::network + +// private functions +namespace flame_ide +{namespace handler +{namespace network +{ +namespace // anonymous +{ + +using InternalAllocator = templates::allocator::ObjectAllocator; + +Handler::Internal *makeInternal() noexcept +{ + return InternalAllocator{}.construct(); +} + +void destroyInternal(Handler::Internal *&internal) noexcept +{ + InternalAllocator{}.destroy(internal); +} + +} // namespace anonymous +}}} // namespace flame_ide::os::network diff --git a/src/Handler/Network/Headers.cmake b/src/Handler/Network/Headers.cmake new file mode 100644 index 00000000..bc575dbe --- /dev/null +++ b/src/Handler/Network/Headers.cmake @@ -0,0 +1,9 @@ +set (HEADER_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/Functions.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Internal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Notificator.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Tcp.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Udp.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkerBase.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Workers.hpp +) diff --git a/src/Handler/Network/Internal.cpp b/src/Handler/Network/Internal.cpp new file mode 100644 index 00000000..cd941f26 --- /dev/null +++ b/src/Handler/Network/Internal.cpp @@ -0,0 +1,51 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::Internal::Internal() noexcept + : workers{ udpData } + , notificators{ + workers.udp().serverNotifier() + , workers.udp().clientNotifier() + } +{ + os::async::network::Registrar registration; + + registration.setNotificator(notificators.udpServer); + registration.setNotificator(notificators.udpClient); + + // TODO + registration.setNotificator(notificators.tcpServer); + registration.setNotificator(notificators.tcpAcceptedConnecton); + registration.setNotificator(notificators.tcpClient); +} + +Handler::Internal::~Internal() noexcept +{ + os::async::network::Registrar{}.unsetNotificators(); +} + +Handler::Udp &Handler::Internal::udp() noexcept +{ + return udpData; +} + +Handler::Tcp &Handler::Internal::tcp() noexcept +{ + return tcpData; +} + +os::Status Handler::Internal::start() noexcept +{ + return workers.start(), os::STATUS_SUCCESS; +} + +os::Status Handler::Internal::stop() noexcept +{ + return workers.stop(), os::STATUS_SUCCESS; +} + +}}} // namespace flame_ide::os::network diff --git a/src/Handler/Network/Internal.hpp b/src/Handler/Network/Internal.hpp new file mode 100644 index 00000000..617c2714 --- /dev/null +++ b/src/Handler/Network/Internal.hpp @@ -0,0 +1,56 @@ +#ifndef HANDLERINTERNAL_HPP +#define HANDLERINTERNAL_HPP + +#include + +#include +#include + +#include +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{ +}}} // namespace flame_ide::handler::network + +namespace flame_ide +{namespace handler +{namespace network +{ + +class Handler::Internal +{ +public: + Internal() noexcept; + ~Internal() noexcept; + + /// @brief udp + /// @return + Udp &udp() noexcept; + + /// @brief tcp + /// @return + Tcp &tcp() noexcept; + + /// @brief start + /// @return + os::Status start() noexcept; + + /// @brief stop + /// @return + os::Status stop() noexcept; + +private: + Handler::Udp udpData; ///< + Handler::Tcp tcpData; ///< + Workers workers; ///< + Notificators notificators; ///< TODO: Need workers +}; + +}}} // namespace flame_ide::handler::network + +#endif // HANDLERINTERNAL_HPP diff --git a/src/Handler/Network/Notificator.cpp b/src/Handler/Network/Notificator.cpp new file mode 100644 index 00000000..c8e99172 --- /dev/null +++ b/src/Handler/Network/Notificator.cpp @@ -0,0 +1,34 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +void ServerNotificator::operator()() noexcept +{} + +void AcceptedConnectonNotificator::operator()() noexcept +{} + +void ClientNotificator::operator()() noexcept +{} + +}}}} // namespace flame_ide::handler::network::tcp + +namespace flame_ide +{namespace handler +{namespace network +{ + +Notificators::Notificators( + WorkerBase::Notifier udpServerNotifier + , WorkerBase::Notifier udpClientNotifier +) noexcept + : udpServer{ udpServerNotifier } + , udpClient{ udpClientNotifier } +{} + +}}} // namespace flame_ide::handler::network + diff --git a/src/Handler/Network/Notificator.hpp b/src/Handler/Network/Notificator.hpp new file mode 100644 index 00000000..336ff783 --- /dev/null +++ b/src/Handler/Network/Notificator.hpp @@ -0,0 +1,60 @@ +#ifndef HANDLERNOTIFICATOR_HPP +#define HANDLERNOTIFICATOR_HPP + +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +class ServerNotificator: + public ::flame_ide::os::async::network::TcpServerNotificatorBase +{ +public: + virtual void operator()() noexcept override; +}; + +class AcceptedConnectonNotificator: + public ::flame_ide::os::async::network + ::TcpAcceptedConnectionNotificatorBase +{ +public: + virtual void operator()() noexcept override; +}; + +class ClientNotificator: + public ::flame_ide::os::async::network::TcpClientNotificatorBase +{ +public: + virtual void operator()() noexcept override; +}; + +}}}} // namespace flame_ide::handler::network::tcp + +namespace flame_ide +{namespace handler +{namespace network +{ + +struct Notificators +{ + Notificators( + WorkerBase::Notifier udpServerNotifier + , WorkerBase::Notifier udpClientNotifier + ) noexcept; + + udp::ServerNotificator udpServer; + udp::ClientNotificator udpClient; + + tcp::ServerNotificator tcpServer; + tcp::AcceptedConnectonNotificator tcpAcceptedConnecton; + tcp::ClientNotificator tcpClient; +}; + +}}} // namespace flame_ide::handler::network + +#endif // HANDLERNOTIFICATOR_HPP diff --git a/src/Handler/Network/ServerHandle.cpp b/src/Handler/Network/ServerHandle.cpp new file mode 100644 index 00000000..877c8ee2 --- /dev/null +++ b/src/Handler/Network/ServerHandle.cpp @@ -0,0 +1,24 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::ServerHandle::~ServerHandle() +{ + if (operator bool()) + callbackDeregistrate(this); +} + +Handler::ServerHandle::operator bool() const noexcept +{ + return object && callbackGetSessionHandle && callbackDeregistrate; +} + +Handler::ExpectedSessionHandle Handler::ServerHandle::getSessionHandle() noexcept +{ + return callbackGetSessionHandle(object); +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/SessionHandle.cpp b/src/Handler/Network/SessionHandle.cpp new file mode 100644 index 00000000..2e41a766 --- /dev/null +++ b/src/Handler/Network/SessionHandle.cpp @@ -0,0 +1,37 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::SessionHandle::~SessionHandle() +{ + if (operator bool()) + callbackDeregistrate(this); +} + +Handler::SessionHandle::operator bool() const noexcept +{ + return object && callbackBytesToRead && callbackReceive && callbackSend + && callbackDeregistrate; +} + +Types::ssize_t Handler::SessionHandle::bytesToRead() const noexcept +{ + return callbackBytesToRead(object); +} + +Types::ssize_t +Handler::SessionHandle::receive(templates::Range bytes) noexcept +{ + return callbackReceive(object, bytes); +} + +Types::ssize_t +Handler::SessionHandle::send(templates::Range bytes) noexcept +{ + return callbackSend(object, bytes); +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/Sources.cmake b/src/Handler/Network/Sources.cmake new file mode 100644 index 00000000..5250f85a --- /dev/null +++ b/src/Handler/Network/Sources.cmake @@ -0,0 +1,11 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/Handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Internal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Notificator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerHandle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SessionHandle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Tcp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Udp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkerBase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Workers.cpp +) diff --git a/src/Handler/Network/Tcp.cpp b/src/Handler/Network/Tcp.cpp new file mode 100644 index 00000000..6d242b8d --- /dev/null +++ b/src/Handler/Network/Tcp.cpp @@ -0,0 +1,48 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{ +namespace // anonymous +{ + +struct SeverHandleData +{ + tcp::Server *server; + Handler::Tcp *storage; +}; + +} // namespace anonymous +}}} // namespace flame_ide::handler::network + +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::ExpectedServerHandle Handler::Tcp::push(os::network::TcpServer &&server) noexcept +{ + flame_ide::unused(server); + return { os::STATUS_FAILED }; +} + +Handler::ExpectedSessionHandle Handler::Tcp::push(os::network::TcpClient &&client) noexcept +{ + flame_ide::unused(client); + return { os::STATUS_FAILED }; +} + +Handler::ExpectedTcpServer Handler::Tcp::pop(Handler::ServerHandle &handle) +{ + flame_ide::unused(handle); + return { os::STATUS_FAILED }; +} + +Handler::ExpectedTcpClient Handler::Tcp::pop(Handler::SessionHandle &handle) +{ + flame_ide::unused(handle); + return { os::STATUS_FAILED }; +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/Tcp.hpp b/src/Handler/Network/Tcp.hpp new file mode 100644 index 00000000..7e474d17 --- /dev/null +++ b/src/Handler/Network/Tcp.hpp @@ -0,0 +1,40 @@ +#ifndef HANDLER_INTERNAL_TCP_HPP +#define HANDLER_INTERNAL_TCP_HPP + +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +class Handler::Tcp +{ +public: + using CallbackGetSessionHandle = Handler::ServerHandle::CallbackGetSessionHandle; + +public: + // TODO + Handler::ExpectedServerHandle push(os::network::TcpServer &&server) noexcept; + // TODO + Handler::ExpectedSessionHandle push(os::network::TcpClient &&client) noexcept; + + // TODO + Handler::ExpectedTcpServer pop(Handler::ServerHandle &handle); + // TODO + Handler::ExpectedTcpClient pop(Handler::SessionHandle &handle); + + /// @brief serverHandleCallback + /// @return + // TODO + CallbackGetSessionHandle serverHandleCallback() const noexcept; + +private: + tcp::Tcp tcp; +}; + +}}} // namespace flame_ide::handler::network + +#endif // HANDLER_INTERNAL_TCP_HPP diff --git a/src/Handler/Network/Tcp/CMakeLists.txt b/src/Handler/Network/Tcp/CMakeLists.txt new file mode 100644 index 00000000..23621c92 --- /dev/null +++ b/src/Handler/Network/Tcp/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.14) + +set(NAME Handler.Network.Tcp) +set(NAME_ALIAS Handler::Network::Tcp) +set(INCLUDE_PATHS ${FLAME_INCLUDE_PATH}) + +set(DEPENDENCY_HEADER_TARGETS + ${FLAME_NAMESPACE}::Os::Network::Headers +) + +get_sources(FILE_LIST) +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${GENERATED_INCLUDE_PATH}" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + + NO_RTTI + NO_EXCEPTIONS +) diff --git a/src/Handler/Network/Tcp/Client.hpp b/src/Handler/Network/Tcp/Client.hpp new file mode 100644 index 00000000..239023cb --- /dev/null +++ b/src/Handler/Network/Tcp/Client.hpp @@ -0,0 +1,58 @@ +#ifndef HANDLER_INTERNAL_TCPCLIENT_HPP +#define HANDLER_INTERNAL_TCPCLIENT_HPP + +#include + +#include +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +class Client +{ +public: + static_assert( + Constants::CLIENT_INPUT_BUFFER_SIZE != 0 + , "Input buffer size for TCP clients is 0" + ); + static_assert( + Constants::CLIENT_OUTPUT_BUFFER_SIZE != 0 + , "Output buffer size for TCP clients is 0" + ); + +public: + using Optional = ::flame_ide::templates::Optional; + + using InputBuffer = ::flame_ide::templates::CircularArray< + ::flame_ide::byte_t, Constants::CLIENT_INPUT_BUFFER_SIZE + >; + using OutputBuffer = ::flame_ide::templates::CircularArray< + ::flame_ide::byte_t, Constants::CLIENT_OUTPUT_BUFFER_SIZE + >; + using TempBuffer = ::flame_ide::templates::Array< + ::flame_ide::byte_t + , ( + Constants::CLIENT_INPUT_BUFFER_SIZE + > Constants::CLIENT_OUTPUT_BUFFER_SIZE + ) ? Constants::CLIENT_INPUT_BUFFER_SIZE : Constants::CLIENT_OUTPUT_BUFFER_SIZE + >; + +public: + templates::UniquePointer input; + templates::UniquePointer output; + templates::UniquePointer tmp; + + Optional client; +}; + +}}}} // namespace flame_ide::handler::network::tcp + +#endif // HANDLERINTERNALTCPCLIENT_HPP diff --git a/src/Handler/Network/Tcp/Config.hpp b/src/Handler/Network/Tcp/Config.hpp new file mode 100644 index 00000000..495e20ee --- /dev/null +++ b/src/Handler/Network/Tcp/Config.hpp @@ -0,0 +1,42 @@ +#ifndef HANDLER_INTERNAL_TCPCONFIG_HPP +#define HANDLER_INTERNAL_TCPCONFIG_HPP + +#include +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +struct Constants: ::flame_ide::NonCreational +{ + static constexpr Types::size_t NUMBER_OF_SERVERS = + generated::network::Config::TCP_SERVERS; + static constexpr Types::size_t NUMBER_OF_SERVERS_CONNECTIONS = + generated::network::Config::TCP_SERVER_BACKLOG; + + static constexpr Types::size_t NUMBER_OF_CLIENTS = + generated::network::Config::TCP_CLIENTS; + + static constexpr Types::size_t SERVER_INPUT_BUFFER_SIZE = + generated::network::Config::TCP_SERVER_INPUT_BUFFER_SIZE; + static constexpr Types::size_t SERVER_OUTPUT_BUFFER_SIZE = + generated::network::Config::TCP_SERVER_OUTPUT_BUFFER_SIZE; + + static constexpr Types::size_t CLIENT_INPUT_BUFFER_SIZE = + generated::network::Config::TCP_CLIENT_INPUT_BUFFER_SIZE; + static constexpr Types::size_t CLIENT_OUTPUT_BUFFER_SIZE = + generated::network::Config::TCP_CLIENT_OUTPUT_BUFFER_SIZE; + + static constexpr Types::size_t NUMBER_OF_SOCKETS = + Constants::NUMBER_OF_SERVERS * (1 + Constants::NUMBER_OF_SERVERS_CONNECTIONS) + + Constants::NUMBER_OF_CLIENTS; +}; + +}}}} // namespace flame_ide::handler::network::tcp + +#endif // HANDLER_INTERNAL_TCPCONFIG_HPP diff --git a/src/Handler/Network/Tcp/Headers.cmake b/src/Handler/Network/Tcp/Headers.cmake new file mode 100644 index 00000000..8db2e245 --- /dev/null +++ b/src/Handler/Network/Tcp/Headers.cmake @@ -0,0 +1,8 @@ +set (HEADER_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/Client.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Config.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/InternalData.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Server.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Tcp.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Types.hpp +) diff --git a/src/Handler/Network/Tcp/InternalData.cpp b/src/Handler/Network/Tcp/InternalData.cpp new file mode 100644 index 00000000..872578ee --- /dev/null +++ b/src/Handler/Network/Tcp/InternalData.cpp @@ -0,0 +1,50 @@ +#include + +namespace flame_ide +{namespace os +{namespace network +{namespace tcp +{namespace callbacks +{ + +// client + +// TODO +Types::ssize_t clientBytesToRead(void * /* data */) noexcept +{ + return os::STATUS_FAILED; +} + +// TODO +Types::ssize_t clientReceive(void * /* data */, templates::Range) noexcept +{ + return os::STATUS_FAILED; +} + +// TODO +Types::ssize_t clientSend(void * /* data */, templates::Range) noexcept +{ + return os::STATUS_FAILED; +} + +// server + +// TODO +Types::ssize_t serverBytesToRead(void * /* data */) noexcept +{ + return os::STATUS_FAILED; +} + +// TODO +Types::ssize_t serverReceive(void * /* data */, templates::Range) noexcept +{ + return os::STATUS_FAILED; +} + +// TODO +Types::ssize_t serverSend(void * /* data */, templates::Range) noexcept +{ + return os::STATUS_FAILED; +} + +}}}}} // namespace flame_ide::os::network::udp::callbacks diff --git a/src/Handler/Network/Tcp/InternalData.hpp b/src/Handler/Network/Tcp/InternalData.hpp new file mode 100644 index 00000000..dfdc8027 --- /dev/null +++ b/src/Handler/Network/Tcp/InternalData.hpp @@ -0,0 +1,38 @@ +#ifndef HANDLER_INTERNAL_TCPDATA_HPP +#define HANDLER_INTERNAL_TCPDATA_HPP + +#include +#include + +namespace flame_ide +{namespace os +{namespace network +{namespace tcp +{namespace callbacks +{ + +// client + +// TODO +Types::ssize_t clientBytesToRead(void *data) noexcept; + +// TODO +Types::ssize_t clientReceive(void *data, templates::Range) noexcept; + +// TODO +Types::ssize_t clientSend(void *data, templates::Range) noexcept; + +// server + +// TODO +Types::ssize_t serverBytesToRead(void *data) noexcept; + +// TODO +Types::ssize_t serverReceive(void *data, templates::Range) noexcept; + +// TODO +Types::ssize_t serverSend(void *data, templates::Range) noexcept; + +}}}}} // namespace flame_ide::os::network::udp::callbacks + +#endif // HANDLER_INTERNAL_TCPDATA_HPP diff --git a/src/Handler/Network/Tcp/Server.hpp b/src/Handler/Network/Tcp/Server.hpp new file mode 100644 index 00000000..b3cc907f --- /dev/null +++ b/src/Handler/Network/Tcp/Server.hpp @@ -0,0 +1,67 @@ +#ifndef HANDLER_INTERNAL_TCPSERVER_HPP +#define HANDLER_INTERNAL_TCPSERVER_HPP + +#include + +#include +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +class Server +{ +public: + static_assert( + Constants::SERVER_INPUT_BUFFER_SIZE != 0 + , "Input buffer size for TCP servers is 0" + ); + static_assert( + Constants::SERVER_OUTPUT_BUFFER_SIZE != 0 + , "Output buffer size for TCP servers is 0" + ); + static_assert( + Constants::NUMBER_OF_SERVERS_CONNECTIONS != 0 + , "TCP server's backlog is 0" + ); + +public: + using InputBuffer = Buffer; + using OutputBuffer = Buffer; + using TempBuffer = TemporaryBuffer< + Constants::SERVER_INPUT_BUFFER_SIZE, Constants::SERVER_OUTPUT_BUFFER_SIZE + >; + + using Optional = templates::Optional; + using OptionalConnection = templates::Optional< + flame_ide::os::network::TcpServer::WithClient + >; + +public: + struct Connection + { + templates::UniquePointer input; + templates::UniquePointer output; + templates::UniquePointer tmp; + + OptionalConnection client; + }; + using Connections = ::flame_ide::templates::StaticArray< + Connection, Constants::NUMBER_OF_SERVERS_CONNECTIONS + >; + +public: + Optional server; + Connections connections; +}; + +}}}} // namespace flame_ide::handler::network::tcp + +#endif // HANDLER_INTERNAL_TCPSERVER_HPP diff --git a/src/Handler/Network/Tcp/Sources.cmake b/src/Handler/Network/Tcp/Sources.cmake new file mode 100644 index 00000000..8d926f36 --- /dev/null +++ b/src/Handler/Network/Tcp/Sources.cmake @@ -0,0 +1,4 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/InternalData.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Tcp.cpp +) diff --git a/src/Handler/Network/Tcp/Tcp.cpp b/src/Handler/Network/Tcp/Tcp.cpp new file mode 100644 index 00000000..0e2d483f --- /dev/null +++ b/src/Handler/Network/Tcp/Tcp.cpp @@ -0,0 +1,78 @@ +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +Server *Tcp::push(os::network::TcpServer &&server) noexcept +{ + if (!initPointer(servers, serversSpin)) + return nullptr; + + return pushData(servers, serversSpin + , /* check = */ [](const Server &i) -> const auto & + { + return i.server; + } + , /* assignTo = */ [&server](Server &handle) + { + handle.server = flame_ide::move(server); + } + ); +} + +os::network::TcpServer Tcp::pop(Server *server) noexcept +{ + if (!server) + return {}; + + return popData(servers, serversSpin, server + , /* check = */ [](const Server &input, const Server &internal) -> bool + { + if (!(input.server) || !(internal.server)) + return false; + + return input.server->native().descriptor + == internal.server->native().descriptor; + } + , /* returnData = */ [](Server &internal) -> os::network::TcpServer + { + os::network::TcpServer server = flame_ide::move(*internal.server); + return server; + } + ); +} + +Client *Tcp::push(os::network::TcpClient &&/*client*/) noexcept +{ +// if (!initPointer(clients, clientsSpin)) + return nullptr; + +// return assignData(clients, clientsSpin +// , /* check = */ [](const Client &i) -> const auto & +// { +// return i.client; +// } +// , /* assignTo = */ [&client](Client &handle) +// { +// handle.client = flame_ide::move(client); +// } +// ); +} + +os::network::TcpClient Tcp::pop(Client */*client*/) noexcept +{ +// if (!client) + return {}; +// if (!isPointer(clients, clientsSpin)) +// return; +// +// flame_ide::unused(client); +} + +}}}} // namespace flame_ide::handler::network::tcp diff --git a/src/Handler/Network/Tcp/Tcp.hpp b/src/Handler/Network/Tcp/Tcp.hpp new file mode 100644 index 00000000..fbb767b5 --- /dev/null +++ b/src/Handler/Network/Tcp/Tcp.hpp @@ -0,0 +1,73 @@ +#ifndef HANDLER_INTERNAL_TCPTCP_HPP +#define HANDLER_INTERNAL_TCPTCP_HPP + +#include +#include + +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +// WARNING: using UniquePointer because malloc doen't work with big sizes +using Servers = ChooseType< + Constants::NUMBER_OF_SERVERS != 0 + , templates::StaticArray< + templates::UniquePointer, Constants::NUMBER_OF_SERVERS + > + , ::flame_ide::Empty +>::Type; + +// WARNING: using UniquePointer because malloc doen't work with big sizes +using Clients = ::flame_ide::ChooseType< + Constants::NUMBER_OF_CLIENTS != 0 + , templates::StaticArray< + templates::UniquePointer, Constants::NUMBER_OF_CLIENTS + > + , ::flame_ide::Empty +>::Type; + +using SocketDescriptors = ChooseType< + Constants::NUMBER_OF_SOCKETS != 0 + , templates::StaticArray< + os::SocketDescriptor, Constants::NUMBER_OF_SOCKETS + > + , ::flame_ide::Empty +>::Type; + +// WARNING: using UniquePointer because malloc doen't work with big sizes +using AcceptedConnections = templates::StaticArray< + templates::UniquePointer + , Constants::NUMBER_OF_SERVERS_CONNECTIONS +>; + +struct Tcp +{ +public: + Server *push(os::network::TcpServer &&server) noexcept; + os::network::TcpServer pop(Server *server) noexcept; + + Client *push(os::network::TcpClient &&client) noexcept; + os::network::TcpClient pop(Client *client) noexcept; + +public: + templates::UniquePointer servers = decltype(servers)::makeEmpty(); + templates::UniquePointer acceptedConnctions + /* = decltype(acceptedConnctions)::makeEmpty()*/; + + templates::UniquePointer clients/* = decltype(clients)::makeEmpty()*/; + SocketDescriptors socketDescriptors; + + os::threads::Spin serversSpin; + os::threads::Spin acceptedConnctionsSpin; + os::threads::Spin clientsSpin; +}; + +}}}} // namespace flame_ide::handler::network::tcp + +#endif // HANDLER_INTERNAL_TCPTCP_HPP diff --git a/src/Handler/Network/Tcp/Types.hpp b/src/Handler/Network/Tcp/Types.hpp new file mode 100644 index 00000000..f566f600 --- /dev/null +++ b/src/Handler/Network/Tcp/Types.hpp @@ -0,0 +1,48 @@ +#ifndef HANDLER_INTERNAL_TCPTYPES_HPP +#define HANDLER_INTERNAL_TCPTYPES_HPP + +#include +#include +#include + +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{ + +template +using Buffer = templates::CircularArray; + +template +using TemporaryBuffer = templates::Array< + byte_t + , ChooseType< + (BUFFER_SIZE1 > BUFFER_SIZE2) + , IntegralConstant + , IntegralConstant + >::Type::VALUE +>; + +struct AcceptedConnection +{ + constexpr AcceptedConnection() = default; + constexpr bool operator==(AcceptedConnection connection) const noexcept + { + return server == connection.server && client == connection.client; + } + + os::SocketAddressIn address = {}; + os::SocketDescriptor server = os::SOCKET_INVALID.descriptor; + os::SocketDescriptor client = os::SOCKET_INVALID.descriptor; + +}; + +}}}} // namespace flame_ide::handler::network::tcp + +#endif // HANDLER_INTERNAL_TCPTYPES_HPP diff --git a/src/Handler/Network/Udp.cpp b/src/Handler/Network/Udp.cpp new file mode 100644 index 00000000..fb02fba5 --- /dev/null +++ b/src/Handler/Network/Udp.cpp @@ -0,0 +1,276 @@ +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +Handler::ExpectedServerHandle +Handler::Udp::push(os::network::UdpServer &&server) noexcept +{ + ::flame_ide::ReferenceWrapper udpServer = storage.push(move(server)); + if (!udpServer) + return { os::STATUS_FAILED }; + + Handler::ServerHandle handle; + handle.object = Handler::ServerHandle::Object{ + ServerHandleData{ nullptr, udpServer } + }; + handle.callbackGetSessionHandle = serverHandleCallback(); + handle.callbackDeregistrate = nullptr; + return { flame_ide::move(handle) }; +} + +Handler::ExpectedSessionHandle +Handler::Udp::push(os::network::UdpClient &&client) noexcept +{ + ::flame_ide::ReferenceWrapper udpClient = storage.push(move(client)); + if (!udpClient) + return { os::STATUS_FAILED }; + + Handler::SessionHandle handle; + handle.object = Handler::SessionHandle::Object{ + SessionHandleData{ nullptr, udp::ClientCommunicationData{ udpClient } } + }; + handle.callbackBytesToRead = Handler::Udp::clientCallbackBytesToRead(); + handle.callbackReceive = Handler::Udp::clientCallbackReceive(); + handle.callbackSend = Handler::Udp::clientCallbackSend(); + handle.callbackDeregistrate = nullptr; + return { flame_ide::move(handle) }; +} + +Handler::ExpectedUdpServer Handler::Udp::pop(Handler::ServerHandle &handle) +{ + if (!(handle.object && handle.callbackGetSessionHandle)) + return { os::STATUS_FAILED }; + + auto data = handle.object.move(); + auto server = storage.pop(data.server); + if (!server) + return { os::STATUS_FAILED }; + + handle.callbackGetSessionHandle = nullptr; + handle.callbackDeregistrate = nullptr; + return { flame_ide::move(server) }; +} + +Handler::ExpectedUdpClient Handler::Udp::pop(Handler::SessionHandle &handle) +{ + if(!(handle.object && handle.callbackBytesToRead && handle.callbackReceive + && handle.callbackSend)) + return { os::STATUS_FAILED }; + + auto data = handle.object.move(); + auto client = storage.pop(data.data.client); + if (!client) + return { os::STATUS_FAILED }; + + handle.callbackBytesToRead = nullptr; + handle.callbackReceive = nullptr; + handle.callbackSend = nullptr; + handle.callbackDeregistrate = nullptr; + return { flame_ide::move(client) }; +} + +void Handler::Udp::process( + udp::ServerProcessor &serverProcessor, os::async::network::AsyncEvent event +) +{ + storage.process(serverProcessor, event); +} + +void Handler::Udp::process( + udp::ClientProcessor &clientProcessor, os::async::network::AsyncEvent event +) +{ + storage.process(clientProcessor, event); +} + +// server + +Handler::Udp::CallbackGetSessionHandle Handler::Udp::serverHandleCallback() const noexcept +{ + static const auto callback = [](ServerHandle::Object &object) + -> Handler::ExpectedSessionHandle + { + static const auto empty = [](void *) -> void {}; + + if (!object) + return { os::STATUS_FAILED }; + + auto server = object.get().server; + + // В очередь приходят сообщения + auto message = server->input().getFilledMessage(); + if (!message) + return { os::STATUS_FAILED }; + + { + flame_ide::os::threads::Locker messageLock{ message->spin }; + if (message->state != udp::MessageState::READY) + return { os::STATUS_FAILED }; + + message->state = udp::MessageState::PROCESSING; + } + + Handler::SessionHandle sessionHandle; + sessionHandle.object = Handler::SessionHandle::Object{ + udp::ServerCommunicationData{ message, &server->output() } + }; + sessionHandle.callbackBytesToRead = Handler::Udp::serverCallbackBytesToRead(); + sessionHandle.callbackReceive = Handler::Udp::serverCallbackReceive(); + sessionHandle.callbackSend = Handler::Udp::serverCallbackSend(); + sessionHandle.callbackDeregistrate = + reinterpret_cast(+empty); + + return { flame_ide::move(sessionHandle) }; + }; + return reinterpret_cast(+callback); +}; + +Handler::Udp::CallbackServerDeregistrate +Handler::Udp::serverCallbackDeregistrate() noexcept +{ + static const auto callback = [](ServerHandle *handle) -> void + { + auto handleData = handle->object.get(); + const auto server = handleData.handler->popUdp(*handle); + flame_ide::unused(server); + }; + return (+callback); +} + +Handler::Udp::CallbackSessionDeregistrate +Handler::Udp::clientCallbackDeregistrate() noexcept +{ + static const auto callback = [](SessionHandle *handle) -> void + { + auto handleData = handle->object.get(); + const auto client = handleData.handler->popUdp(*handle); + flame_ide::unused(client); + }; + return (+callback); +} + +udp::ServerCommunicationData *Handler::Udp::serverToCommunicationData( + Handler::SessionHandle::Object &object +) noexcept +{ + if (!object) + return nullptr; + + return &object.get(); +} + +const udp::ServerCommunicationData *Handler::Udp::serverToConstCommunicationData( + const Handler::SessionHandle::Object &object +) noexcept +{ + if (!object) + return nullptr; + + return &object.get(); +} + +Handler::Udp::CallbackBytesToRead Handler::Udp::serverCallbackBytesToRead() noexcept +{ + static const auto callback = [](const Handler::SessionHandle::Object &object) + -> ::flame_ide::Types::ssize_t + { + const auto *data = Handler::Udp::serverToConstCommunicationData(object); + return data->bytesToRead(); + }; + return reinterpret_cast(+callback); +} + +Handler::Udp::CallbackReceive Handler::Udp::serverCallbackReceive() noexcept +{ + static const auto callback = []( + Handler::SessionHandle::Object &object + , ::flame_ide::templates::Range range + ) -> ::flame_ide::Types::ssize_t + { + auto *data = Handler::Udp::serverToCommunicationData(object); + return data->receive(range); + }; + return reinterpret_cast(+callback); +} + +Handler::Udp::CallbackSend Handler::Udp::serverCallbackSend() noexcept +{ + static const auto callback = []( + Handler::SessionHandle::Object &object + , ::flame_ide::templates::Range range + ) -> ::flame_ide::Types::ssize_t + { + auto *data = Handler::Udp::serverToCommunicationData(object); + return data->send(range); + }; + return reinterpret_cast(+callback); +} + +// client + +udp::ClientCommunicationData *Handler::Udp::clientToCommunicationData( + Handler::SessionHandle::Object &object +) noexcept +{ + if (!object) + return nullptr; + + return &object.get(); +} + +const udp::ClientCommunicationData *Handler::Udp::clientToConstCommunicationData( + const Handler::SessionHandle::Object &object +) noexcept +{ + if (!object) + return nullptr; + + return &object.get(); +} + +Handler::Udp::CallbackBytesToRead Handler::Udp::clientCallbackBytesToRead() noexcept +{ + static const auto callback = [](const Handler::SessionHandle::Object &object) + -> Types::ssize_t + { + const auto *data = Handler::Udp::clientToConstCommunicationData(object); + return data->bytesToRead(); + }; + + return reinterpret_cast(+callback); +} + +Handler::Udp::CallbackReceive Handler::Udp::clientCallbackReceive() noexcept +{ + static const auto callback = []( + Handler::SessionHandle::Object &object + , ::flame_ide::templates::Range range + ) -> Types::ssize_t + { + auto *data = Handler::Udp::clientToCommunicationData(object); + return data->receive(range); + }; + + return reinterpret_cast(+callback); +} + +Handler::Udp::CallbackSend Handler::Udp::clientCallbackSend() noexcept +{ + static const auto callback = []( + Handler::SessionHandle::Object &object + , ::flame_ide::templates::Range range + ) -> Types::ssize_t + { + auto *data = Handler::Udp::clientToCommunicationData(object); + return data->send(range); + }; + + return reinterpret_cast(+callback); +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/Udp.hpp b/src/Handler/Network/Udp.hpp new file mode 100644 index 00000000..633d0484 --- /dev/null +++ b/src/Handler/Network/Udp.hpp @@ -0,0 +1,146 @@ +#ifndef HANDLER_INTERNAL_UDP_HPP +#define HANDLER_INTERNAL_UDP_HPP + +#include + +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +class Handler::Udp +{ +public: + using CallbackGetSessionHandle = Handler::ServerHandle::CallbackGetSessionHandle; + using CallbackServerDeregistrate = Handler::ServerHandle::CallbackDeregistrate; + using CallbackSessionDeregistrate = Handler::SessionHandle::CallbackDeregistrate; + + using CallbackBytesToRead = Handler::SessionHandle::CallbackBytesToRead; + using CallbackReceive = Handler::SessionHandle::CallbackReceive; + using CallbackSend = Handler::SessionHandle::CallbackSend; + +public: + struct ServerHandleData + { + ::flame_ide::ReferenceWrapper handler; + ::flame_ide::ReferenceWrapper server; + }; + + struct SessionHandleData + { + Handler *handler; + udp::ClientCommunicationData data; + }; + +public: + Handler::ExpectedServerHandle push(os::network::UdpServer &&server) noexcept; + Handler::ExpectedSessionHandle push(os::network::UdpClient &&client) noexcept; + + Handler::ExpectedUdpServer pop(Handler::ServerHandle &handle); + Handler::ExpectedUdpClient pop(Handler::SessionHandle &handle); + +public: // For Workers + void process( + udp::ServerProcessor &serverProcessor, os::async::network::AsyncEvent event + ); + void process( + udp::ClientProcessor &clientProcessor, os::async::network::AsyncEvent event + ); + +public: // Callbacks + /// @brief serverHandleCallback + /// @return + CallbackGetSessionHandle serverHandleCallback() const noexcept; + + /// + /// @brief serverCallbackDeregistrate + /// @return + /// + static CallbackServerDeregistrate serverCallbackDeregistrate() noexcept; + + /// + /// @brief serverCallbackDeregistrate + /// @return + /// + static CallbackSessionDeregistrate clientCallbackDeregistrate() noexcept; + +private: + /// @brief serverToCommunicationData + /// @param object + /// @return + static udp::ServerCommunicationData *serverToCommunicationData( + Handler::SessionHandle::Object &object + ) noexcept; + + /// @brief serverToConstCommunicationData + /// @param object + /// @return + static const udp::ServerCommunicationData *serverToConstCommunicationData( + const Handler::SessionHandle::Object &object + ) noexcept; + + /// @brief serverCallbackBytesToRead + /// @return + /// + static CallbackBytesToRead serverCallbackBytesToRead() noexcept; + + /// + /// @brief serverCallbackReceive + /// @return + /// + static CallbackReceive serverCallbackReceive() noexcept; + + /// + /// @brief serverCallbackSend + /// @return + /// + static CallbackSend serverCallbackSend() noexcept; + + /// + /// @brief clientToCommunicationData + /// @param object + /// @return + /// + static udp::ClientCommunicationData *clientToCommunicationData( + Handler::SessionHandle::Object &object + ) noexcept; + + /// + /// @brief clientToConstCommunicationData + /// @param object + /// @return + /// + static const udp::ClientCommunicationData *clientToConstCommunicationData( + const Handler::SessionHandle::Object &object + ) noexcept; + + /// + /// @brief clientCallbackBytesToRead + /// @return + /// + static CallbackBytesToRead clientCallbackBytesToRead() noexcept; + + /// + /// @brief clientCallbackReceive + /// @return + /// + static CallbackReceive clientCallbackReceive() noexcept; + + /// + /// @brief clientCallbackSend + /// @return + /// + static CallbackSend clientCallbackSend() noexcept; + +private: + udp::Storage storage; +}; + +}}} // namespace flame_ide::handler::network + +#endif // HANDLER_INTERNAL_UDP_HPP diff --git a/src/Handler/Network/Udp/ActualData.hpp b/src/Handler/Network/Udp/ActualData.hpp new file mode 100644 index 00000000..07883d93 --- /dev/null +++ b/src/Handler/Network/Udp/ActualData.hpp @@ -0,0 +1,118 @@ +#ifndef HANDLER_INTERNAL_UDP_ACTUAL_DATA_HPP +#define HANDLER_INTERNAL_UDP_ACTUAL_DATA_HPP + +#include +#include +#include + +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +template +struct ActualData +{ +public: + using Messages = flame_ide::templates::StaticArray< + flame_ide::templates::UniquePointer, SIZE + >; + using MessagesCircularIterator = + ::flame_ide::templates::defaults::CircularForwardIterator< + typename Messages::Iterator + >; + + ::flame_ide::ReferenceWrapper getEmptyMessage() noexcept; + ::flame_ide::ReferenceWrapper getFilledMessage() noexcept; + + ::flame_ide::Types::ssize_t getFilledMessageSize() const noexcept; + +private: + ::flame_ide::Types::size_t amount = 0; + + Messages messages; + MessagesCircularIterator first = MessagesCircularIterator{ + messages.begin(), templates::makeRange(messages.begin(), messages.end()) + }; + MessagesCircularIterator last = first; + + mutable os::threads::Spin spin; +}; + +}}}} // namespace flame_ide::handler::network::udp + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +template +::flame_ide::ReferenceWrapper +ActualData::getEmptyMessage() noexcept +{ + os::threads::Locker lock{ spin }; + + if (amount == SIZE) + return nullptr; + + auto result = last; + ++amount; + ++last; + + { + os::threads::Locker lockMessage{ result->pointer()->spin }; + result->pointer()->state = MessageState::PROCESSING; + } + + return result->pointer(); +} + +template +::flame_ide::ReferenceWrapper +ActualData::getFilledMessage() noexcept +{ + os::threads::Locker lock{ spin }; + + if ((first == last) && (amount == 0)) + return nullptr; + + auto result = first; + --amount; + ++first; + + { + os::threads::Locker lockMessage{ result->pointer()->spin }; + result->pointer()->state = MessageState::PROCESSING; + } + + return result->pointer(); +} + +template +::flame_ide::Types::ssize_t +ActualData::getFilledMessageSize() const noexcept +{ + os::threads::Locker lock{ spin }; + + if ((first == last) && (amount == 0)) + return 0; + + { + const auto &message = *first; + os::threads::Locker messageLocker{ message->spin }; + if (message->state == MessageState::EMPTY) + return 0; + return message->size; + } +} + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_ACTUAL_DATA_HPP diff --git a/src/Handler/Network/Udp/CMakeLists.txt b/src/Handler/Network/Udp/CMakeLists.txt new file mode 100644 index 00000000..ccf01bc7 --- /dev/null +++ b/src/Handler/Network/Udp/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.14) + +set(NAME Handler.Network.Udp) +set(NAME_ALIAS Handler::Network::Udp) +set(INCLUDE_PATHS ${FLAME_INCLUDE_PATH}) + +set(DEPENDENCY_HEADER_TARGETS + ${FLAME_NAMESPACE}::Os::Network::Headers +) + +get_sources(FILE_LIST) +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${GENERATED_INCLUDE_PATH}" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + + NO_RTTI + NO_EXCEPTIONS +) diff --git a/src/Handler/Network/Udp/Client.cpp b/src/Handler/Network/Udp/Client.cpp new file mode 100644 index 00000000..e6725132 --- /dev/null +++ b/src/Handler/Network/Udp/Client.cpp @@ -0,0 +1,106 @@ +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +void ClientMessage::fill(flame_ide::os::network::UdpClient &endpoint) noexcept +{ + os::threads::Locker locker{ spin }; + + auto waitResult = endpoint.wait(); + if (waitResult < 0) + return; + + this->size = endpoint.receive(this->range()); + this->state = MessageState::READY; +} + +Types::ssize_t ClientCommunicationData::bytesToRead() const noexcept +{ + if (!client) + return os::STATUS_FAILED; + + return client->input().getFilledMessageSize(); +} + +Types::ssize_t +ClientCommunicationData::receive(templates::Range range) noexcept +{ + if (!client) + return os::STATUS_FAILED; + + ReferenceWrapper message = client->input().getFilledMessage(); + if (!message) + return os::STATUS_FAILED; + + const auto raiiClear = flame_ide::templates::makeRaiiCaller( + [&message]() + { + message->spin.lock(); + message->state = MessageState::PROCESSING; + } + , [&message]() + { + message->size = 0; + message->state = MessageState::EMPTY; + message->spin.unlock(); + } + ); + + const auto readBytes = flame_ide::minimum( + Types::ssize_t{ message->size } + , Types::ssize_t{ range.end() - range.begin() } + ); + decltype(readBytes) result = flame_ide::templates::copy( + message->bytes.begin(), message->bytes.begin() + readBytes + , range.begin() + ); + if (readBytes != result) + return os::STATUS_FAILED; + + return readBytes; +} + +Types::ssize_t +ClientCommunicationData::send(templates::Range range) noexcept +{ + if (!client) + return os::STATUS_FAILED; + + ReferenceWrapper message = client->output().getEmptyMessage(); + if (!message) + return os::STATUS_FAILED; + + const auto raiiClear = flame_ide::templates::makeRaiiCaller( + [&message]() + { + message->spin.lock(); + message->state = MessageState::PROCESSING; + } + , [&message]() + { + message->state = MessageState::READY; + message->spin.unlock(); + } + ); + + const auto wroteBytes = flame_ide::minimum( + Types::ssize_t{ message->size } + , Types::ssize_t{ range.end() - range.begin() } + ); + decltype(wroteBytes) result = flame_ide::templates::copy( + range.begin(), range.begin() + wroteBytes + , message->bytes.begin() + ); + if (wroteBytes != result) + return os::STATUS_FAILED; + return wroteBytes; +} + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Client.hpp b/src/Handler/Network/Udp/Client.hpp new file mode 100644 index 00000000..d5118568 --- /dev/null +++ b/src/Handler/Network/Udp/Client.hpp @@ -0,0 +1,38 @@ +#ifndef HANDLER_INTERNAL_UDPCLIENT_HPP +#define HANDLER_INTERNAL_UDPCLIENT_HPP + +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +struct ClientMessage: public Message +{ + void fill(flame_ide::os::network::UdpClient &endpoint) noexcept; +}; + +class Client: public Endpoint< + ::flame_ide::os::network::UdpClient, ClientMessage + , Constants::CLIENT_INPUT_QUEUE_SIZE, Constants::CLIENT_OUTPUT_QUEUE_SIZE +> +{}; + +struct ClientCommunicationData +{ + ::flame_ide::ReferenceWrapper client; + + Types::ssize_t bytesToRead() const noexcept; + Types::ssize_t receive(templates::Range range) noexcept; + Types::ssize_t send(templates::Range range) noexcept; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDPCLIENT_HPP diff --git a/src/Handler/Network/Udp/Config.hpp b/src/Handler/Network/Udp/Config.hpp new file mode 100644 index 00000000..4ec0f1ce --- /dev/null +++ b/src/Handler/Network/Udp/Config.hpp @@ -0,0 +1,42 @@ +#ifndef HANDLER_INTERNAL_UDPCONFIG_HPP +#define HANDLER_INTERNAL_UDPCONFIG_HPP + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +struct Constants: ::flame_ide::NonCreational +{ + static constexpr Types::size_t NUMBER_OF_SERVERS = + generated::network::Config::UDP_SERVERS; + static constexpr Types::size_t NUMBER_OF_CLIENTS = + generated::network::Config::UDP_CLIENTS; + + static constexpr Types::size_t MESSAGE_SIZE = + generated::network::Config::UDP_MESSAGE_SIZE; + + static constexpr Types::size_t SERVER_INPUT_QUEUE_SIZE = + generated::network::Config::UDP_SERVER_INPUT_QUEUE_SIZE; + static constexpr Types::size_t SERVER_OUTPUT_QUEUE_SIZE = + generated::network::Config::UDP_SERVER_OUTPUT_QUEUE_SIZE; + + static constexpr Types::size_t CLIENT_INPUT_QUEUE_SIZE = + generated::network::Config::UDP_CLIENT_INPUT_QUEUE_SIZE; + static constexpr Types::size_t CLIENT_OUTPUT_QUEUE_SIZE = + generated::network::Config::UDP_CLIENT_OUTPUT_QUEUE_SIZE; + +private: + static_assert( + MESSAGE_SIZE < ::flame_ide::Constants::MAX_UDP_IPV4_MESSAGE_SIZE + , "UDP IPv4 message is too big. Max size is 65507" + ); +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDPCONFIG_HPP diff --git a/src/Handler/Network/Udp/ContainerTypes.hpp b/src/Handler/Network/Udp/ContainerTypes.hpp new file mode 100644 index 00000000..c07be201 --- /dev/null +++ b/src/Handler/Network/Udp/ContainerTypes.hpp @@ -0,0 +1,30 @@ +#ifndef HANDLER_INTERNAL_UDP_CONTAINER_TYPES_HPP +#define HANDLER_INTERNAL_UDP_CONTAINER_TYPES_HPP + +#include + +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +// WARNING: using UniquePointer because malloc doen't work with big sizes +class Servers: public ::flame_ide::templates::StaticArray< + templates::UniquePointer, Constants::NUMBER_OF_SERVERS +> +{}; + +// WARNING: using UniquePointer because malloc doen't work with big sizes +class Clients: public ::flame_ide::templates::StaticArray< + templates::UniquePointer, Constants::NUMBER_OF_CLIENTS +> +{}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_CONTAINER_TYPES_HPP diff --git a/src/Handler/Network/Udp/Endpoint.hpp b/src/Handler/Network/Udp/Endpoint.hpp new file mode 100644 index 00000000..9a550db7 --- /dev/null +++ b/src/Handler/Network/Udp/Endpoint.hpp @@ -0,0 +1,180 @@ +#ifndef HANDLER_INTERNAL_UDP_ENDPOINT_HPP +#define HANDLER_INTERNAL_UDP_ENDPOINT_HPP + +#include +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +class Endpoint +{ +public: + using Data = EndpointData; + using Optional = flame_ide::templates::Optional; + using ActualInput = ActualData; + using ActualOutput = ActualData; + + bool empty() const noexcept; + void attach(EndpointData &&data) noexcept; + EndpointData detach() noexcept; + + Optional &endpoint() noexcept; + const Optional &endpoint() const noexcept; + + ActualInput &input() noexcept; + const ActualInput &input() const noexcept; + + ActualOutput &output() noexcept; + const ActualOutput &output() const noexcept; + +protected: + Optional osEndpoint; + ActualInput actualInput; + ActualOutput actualOutput; +}; + +}}}} // namespace flame_ide::handler::network::udp + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +bool Endpoint::empty() const noexcept +{ + return !(osEndpoint); +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +void Endpoint::attach( + EndpointData &&data +) noexcept +{ + if (!empty()) + return; + + osEndpoint.set(flame_ide::move(data)); +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +EndpointData +Endpoint::detach() noexcept +{ + if (empty()) + return {}; + + Data data = flame_ide::move(osEndpoint.pull()); + return data; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +typename Endpoint::Optional & +Endpoint::endpoint() noexcept +{ + return osEndpoint; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +const typename Endpoint::Optional & +Endpoint::endpoint() const noexcept +{ + return osEndpoint; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +typename Endpoint::ActualInput & +Endpoint::input() noexcept +{ + return actualInput; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE + > +const typename Endpoint< + EndpointData, MessageType, INPUT_SIZE, OUTPUT_SIZE +>::ActualInput & +Endpoint::input() const noexcept +{ + return actualInput; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE + > +typename Endpoint< +EndpointData, MessageType, INPUT_SIZE, OUTPUT_SIZE +>::ActualOutput & +Endpoint::output() noexcept +{ + return actualOutput; +} + +template< + typename EndpointData + , typename MessageType + , ::flame_ide::Types::size_t INPUT_SIZE + , ::flame_ide::Types::size_t OUTPUT_SIZE +> +const typename Endpoint< + EndpointData, MessageType, INPUT_SIZE, OUTPUT_SIZE +>::ActualOutput & +Endpoint::output() const noexcept +{ + return actualOutput; +} + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_ENDPOINT_HPP diff --git a/src/Handler/Network/Udp/Headers.cmake b/src/Handler/Network/Udp/Headers.cmake new file mode 100644 index 00000000..87fe63c3 --- /dev/null +++ b/src/Handler/Network/Udp/Headers.cmake @@ -0,0 +1,15 @@ +set (HEADER_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/ActualData.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Client.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Config.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ContainerTypes.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Endpoint.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Message.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Notificators.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Processing.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Server.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Storage.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/TypeMapping.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Types.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Workers.hpp +) diff --git a/src/Handler/Network/Udp/Message.cpp b/src/Handler/Network/Udp/Message.cpp new file mode 100644 index 00000000..e3e2b3b4 --- /dev/null +++ b/src/Handler/Network/Udp/Message.cpp @@ -0,0 +1,16 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +::flame_ide::templates::Range<::flame_ide::byte_t *> Message::range() noexcept +{ + return ::flame_ide::templates::makeRange( + bytes.begin().operator->(), bytes.end().operator->() + ); +} + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Message.hpp b/src/Handler/Network/Udp/Message.hpp new file mode 100644 index 00000000..ffe6dbc5 --- /dev/null +++ b/src/Handler/Network/Udp/Message.hpp @@ -0,0 +1,32 @@ +#ifndef HANDLER_INTERNAL_UDP_MESSAGE_HPP +#define HANDLER_INTERNAL_UDP_MESSAGE_HPP + +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +struct Message +{ + ::flame_ide::templates::StaticArray< + ::flame_ide::byte_t, Constants::MESSAGE_SIZE + > bytes; + ::flame_ide::Types::ssize_t size = 0; + MessageState state = MessageState::EMPTY; + + mutable os::threads::Spin spin; + +protected: + ::flame_ide::templates::Range<::flame_ide::byte_t *> range() noexcept; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_MESSAGE_HPP diff --git a/src/Handler/Network/Udp/Notificators.cpp b/src/Handler/Network/Udp/Notificators.cpp new file mode 100644 index 00000000..92d57e3d --- /dev/null +++ b/src/Handler/Network/Udp/Notificators.cpp @@ -0,0 +1,32 @@ +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +// + +ServerNotificator::ServerNotificator(WorkerBase::Notifier notifierInit) + : notifier{ ::flame_ide::move(notifierInit) } +{} + +void ServerNotificator::operator()() noexcept +{ + notifier(); +} + +// + +ClientNotificator::ClientNotificator(WorkerBase::Notifier notifierInit) + : notifier{ ::flame_ide::move(notifierInit) } +{} + +void ClientNotificator::operator()() noexcept +{ + notifier(); +} + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Notificators.hpp b/src/Handler/Network/Udp/Notificators.hpp new file mode 100644 index 00000000..214f587b --- /dev/null +++ b/src/Handler/Network/Udp/Notificators.hpp @@ -0,0 +1,44 @@ +#ifndef HANDLER_INTERNAL_UDP_NOTIFICATORS_HPP +#define HANDLER_INTERNAL_UDP_NOTIFICATORS_HPP + +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +/// +/// \brief The ServerNotificator class +/// +class ServerNotificator: + public ::flame_ide::os::async::network::UdpServerNotificatorBase +{ +public: + ServerNotificator(WorkerBase::Notifier notifierInit); + virtual void operator()() noexcept override; + +private: + WorkerBase::Notifier notifier; +}; + +/// +/// \brief The ClientNotificator class +/// +class ClientNotificator: + public ::flame_ide::os::async::network::UdpClientNotificatorBase +{ +public: + ClientNotificator(WorkerBase::Notifier notifierInit); + virtual void operator()() noexcept override; + +private: + WorkerBase::Notifier notifier; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_NOTIFICATORS_HPP diff --git a/src/Handler/Network/Udp/Processing.cpp b/src/Handler/Network/Udp/Processing.cpp new file mode 100644 index 00000000..4323bf13 --- /dev/null +++ b/src/Handler/Network/Udp/Processing.cpp @@ -0,0 +1,85 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +bool ServerProcessor::operator()( + HandlerEndpointUdpData &storage, os::async::network::AsyncEvent event +) noexcept +{ + ::flame_ide::ReferenceWrapper endpointData{ nullptr }; + { + ::flame_ide::os::threads::Locker lock{ storage.spin }; + for (templates::UniquePointer &pointer : *storage.container) + { + if (!checkEndpoint(pointer, event.descriptor)) + continue; + + endpointData = decltype(endpointData){ pointer.pointer() }; + } + } + if (!endpointData) + return false; + + switch (event.event) + { + case decltype(event.event)::INVALID: + { + return false; + } + + case decltype(event.event)::READ: + { + os::network::UdpServer &endpoint = *endpointData->endpoint(); + + // Message in processing state + ::flame_ide::ReferenceWrapper message + = endpointData->input().getEmptyMessage(); + if (message) + return false; + return message->fill(endpoint); + } + + case decltype(event.event)::WRITE: + { + return false; + } + + case decltype(event.event)::READ_WRITE: + { + return false; + } + + default: + return false; + } +} + +bool ServerProcessor::checkEndpoint( + const ::flame_ide::templates::UniquePointer &endpoint + , os::SocketDescriptor descriptor +) +{ + if (!endpoint || endpoint->empty()) + return false; + + if (endpoint->endpoint()->native().descriptor != descriptor) + return false; + + return true; +} + +// + +bool ClientProcessor::operator()( + HandlerEndpointUdpData &storage, os::async::network::AsyncEvent event +) noexcept +{ + flame_ide::unused(storage, event); + return false; +} + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Processing.hpp b/src/Handler/Network/Udp/Processing.hpp new file mode 100644 index 00000000..48eea140 --- /dev/null +++ b/src/Handler/Network/Udp/Processing.hpp @@ -0,0 +1,63 @@ +#ifndef HANDLER_INTERNAL_UDP_PROCESSING_HPP +#define HANDLER_INTERNAL_UDP_PROCESSING_HPP + +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +// Base class for processing clients and servers + +template +class EndpointProcessor: public flame_ide::FunctorBase< + Container, HandlerEndpointUdpData &, os::async::network::AsyncEvent +> +{ +public: + virtual bool operator()( + HandlerEndpointUdpData &storage + , os::async::network::AsyncEvent event + ) noexcept = 0; +}; + +// + +class ServerProcessor: + public flame_ide::FunctorBase< + bool, HandlerEndpointUdpData &, os::async::network::AsyncEvent + > +{ +public: + virtual bool operator()( + HandlerEndpointUdpData &storage, os::async::network::AsyncEvent event + ) noexcept override; + +private: + static bool checkEndpoint( + const ::flame_ide::templates::UniquePointer &endpoint + , os::SocketDescriptor descriptor + ); +}; + +// + +class ClientProcessor: + public flame_ide::FunctorBase< + bool, HandlerEndpointUdpData &, os::async::network::AsyncEvent + > +{ +public: + virtual bool operator()( + HandlerEndpointUdpData &storage, os::async::network::AsyncEvent event + ) noexcept override; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_PROCESSING_HPP diff --git a/src/Handler/Network/Udp/Server.cpp b/src/Handler/Network/Udp/Server.cpp new file mode 100644 index 00000000..ccf43bab --- /dev/null +++ b/src/Handler/Network/Udp/Server.cpp @@ -0,0 +1,81 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +bool ServerMessage::fill(flame_ide::os::network::UdpServer &endpoint) noexcept +{ + os::threads::Locker lock{ this->spin }; + + auto waitResult = endpoint.wait(); + if (waitResult.getStatus() < 0) + return false; + + this->client = waitResult; + this->size = this->client.receive(this->range()); + this->state = MessageState::READY; + return true; +} + +Types::ssize_t ServerCommunicationData::bytesToRead() const noexcept +{ + if (!message) + return os::STATUS_FAILED; + + os::threads::Locker locker{ message->spin }; + return message->size; +} + +Types::ssize_t ServerCommunicationData::receive(templates::Range range) noexcept +{ + if (!message) + return os::STATUS_FAILED; + + ::flame_ide::Types::ssize_t readData = -1; + { + flame_ide::os::threads::Locker lock{ message->spin }; + + const auto min = ::flame_ide::minimum<::flame_ide::Types::ssize_t>( + (range.end() - range.begin()), message->size + ); + ::flame_ide::templates::copy( + message->bytes.begin(), message->bytes.begin() + min, range.begin() + ); + + message->state = udp::MessageState::EMPTY; + message->size = 0; + + readData = min; + } + return readData; +} + +Types::ssize_t +ServerCommunicationData::send(templates::Range range) noexcept +{ + if (!output) + return os::STATUS_FAILED; + + auto message = output->getEmptyMessage(); + if (!message) + return os::STATUS_FAILED; + { + flame_ide::os::threads::Locker lock{ message->spin }; + + const auto min = ::flame_ide::minimum<::flame_ide::Types::ssize_t>( + (range.end() - range.begin()), message->bytes.capacity() + ); + ::flame_ide::templates::copy( + range.begin(), range.begin() + min, message->bytes.begin() + ); + + message->state = udp::MessageState::READY; + message->size = min; + } + return message->size; +} + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Server.hpp b/src/Handler/Network/Udp/Server.hpp new file mode 100644 index 00000000..44978527 --- /dev/null +++ b/src/Handler/Network/Udp/Server.hpp @@ -0,0 +1,40 @@ +#ifndef HANDLER_INTERNAL_UDPSERVER_HPP +#define HANDLER_INTERNAL_UDPSERVER_HPP + +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +struct ServerMessage: public Message +{ + bool fill(flame_ide::os::network::UdpServer &endpoint) noexcept; + + ::flame_ide::os::network::UdpServer::WithClient client; +}; + +class Server: public Endpoint< + ::flame_ide::os::network::UdpServer, ServerMessage + , Constants::SERVER_INPUT_QUEUE_SIZE, Constants::SERVER_OUTPUT_QUEUE_SIZE +> +{}; + +struct ServerCommunicationData +{ + ::flame_ide::ReferenceWrapper message; + ::flame_ide::ReferenceWrapper output; + + Types::ssize_t bytesToRead() const noexcept; + Types::ssize_t receive(templates::Range range) noexcept; + Types::ssize_t send(templates::Range range) noexcept; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDPSERVER_HPP diff --git a/src/Handler/Network/Udp/Sources.cmake b/src/Handler/Network/Udp/Sources.cmake new file mode 100644 index 00000000..c25ef745 --- /dev/null +++ b/src/Handler/Network/Udp/Sources.cmake @@ -0,0 +1,8 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/Client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Message.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Notificators.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Processing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Server.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Workers.cpp +) diff --git a/src/Handler/Network/Udp/Storage.hpp b/src/Handler/Network/Udp/Storage.hpp new file mode 100644 index 00000000..a27bd4bc --- /dev/null +++ b/src/Handler/Network/Udp/Storage.hpp @@ -0,0 +1,145 @@ +#ifndef HANDLER_INTERNAL_UDPSTORAGE_HPP +#define HANDLER_INTERNAL_UDPSTORAGE_HPP + +#include +#include +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +class Storage +{ +public: + template + auto push(OsEndpoint &&osEndpoint) noexcept + { + static_assert( + IsOsEndpoint::VALUE + , "Input type is not flame_ide::os::network::UdpServer or" + " flame_ide::os::network::UdpClient" + ); + + using HandlerEndpoint = typename EndpointTypeMapper::Type; + using HandlerEndpointData = typename HandlerEndpointDataMapper< + HandlerEndpoint + >::Type; + + HandlerEndpointData &data = getData(); + // Init container if need + { + os::threads::Locker lock{ data.spin }; + if (!data.container) + data.container = decltype(data.container){}; + if (!data.container) + return ::flame_ide::ReferenceWrapper{ nullptr }; + } + + // Push + ::flame_ide::ReferenceWrapper handlerEndpointPointer = nullptr; + { + os::threads::Locker lock{ data.spin }; + for (auto &i : data.container.reference()) + { + if (!i->empty()) + continue; + + handlerEndpointPointer = i.pointer(); + break; + } + if (handlerEndpointPointer) + handlerEndpointPointer->attach(flame_ide::move(osEndpoint)); + } + return handlerEndpointPointer; + } + + template + auto pop(ReferenceWrapper handlerEndpoint) noexcept + { + static_assert( + IsHandlerEndpoint::VALUE + , "Input type is not flame_ide::handler::udp::Server or" + " flame_ide::handler::udp::UdpClient" + ); + + using OsEndpoint = typename EndpointTypeMapper::Type; + using HandlerEndpointData = typename HandlerEndpointDataMapper< + HandlerEndpoint + >::Type; + + if (!handlerEndpoint || handlerEndpoint->empty()) + return OsEndpoint{}; + + HandlerEndpointData &data = getData(); + const auto endpointDescriptor = handlerEndpoint->endpoint()->native().descriptor; + + // Pop + { + os::threads::Locker lock{ data.spin }; + for (auto &i : data.container.reference()) + { + if (i->empty()) + continue; + + const auto internalDescriptor = i->endpoint()->native().descriptor; + if (endpointDescriptor != internalDescriptor) + continue; + + OsEndpoint osEndpoint = flame_ide::move(i->detach()); + return osEndpoint; + } + } + return OsEndpoint{}; + } + + template + void process(EndpointProcessor &processor, os::async::network::AsyncEvent event) + { + using HandlerEndpointData = typename HandlerEndpointDataMapper< + EndpointProcessor + >::Type; + processor(getData(), event); + } + +private: + template + T &getData() noexcept; + +private: + HandlerEndpointUdpData servers; + HandlerEndpointUdpData clients; + +}; + +}}}} // namespace flame_ide::handler::network::udp + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +template<> inline +HandlerEndpointUdpData & +Storage::getData>() noexcept +{ + return servers; +} + +template<> inline +HandlerEndpointUdpData & +Storage::getData>() noexcept +{ + return clients; +} + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDPSTORAGE_HPP diff --git a/src/Handler/Network/Udp/TypeMapping.hpp b/src/Handler/Network/Udp/TypeMapping.hpp new file mode 100644 index 00000000..cde8e810 --- /dev/null +++ b/src/Handler/Network/Udp/TypeMapping.hpp @@ -0,0 +1,147 @@ +#ifndef HANDLER_INTERNAL_UDP_TYPE_MAPPING_HPP +#define HANDLER_INTERNAL_UDP_TYPE_MAPPING_HPP + +#include + +// Forwards + +namespace flame_ide +{namespace os +{namespace network +{ + +class UdpServer; +class UdpClient; + +}}} // namespace flame_ide::os::network + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +class Server; +class Servers; +class ServerProcessor; + +class Client; +class Clients; +class ClientProcessor; + +template +struct HandlerEndpointUdpData; + +}}}} // / namespace flame_ide::handler::network::udp + +// Mapping + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +using ServerMatchingTrait = ::flame_ide::TypeMappingTrait< + os::network::UdpServer, Server +>; +using ClientMatchingTrait = ::flame_ide::TypeMappingTrait< + os::network::UdpClient, Client +>; + +using ServerDataMatchingTrait = ::flame_ide::TypeMappingTrait< + Server, HandlerEndpointUdpData +>; +using ClientDataMatchingTrait = ::flame_ide::TypeMappingTrait< + Client, HandlerEndpointUdpData +>; + +using ServerProcessorMatchingTrait = ::flame_ide::TypeMappingTrait< + ServerProcessor, HandlerEndpointUdpData +>; + +using ClientProcessorMatchingTrait = ::flame_ide::TypeMappingTrait< + ClientProcessor, HandlerEndpointUdpData +>; + +// Integral constants + +template +using IsServer = ::flame_ide::IntegralConstant< + bool + , ::flame_ide::ComparingTypes< + EndpointType, ::flame_ide::os::network::UdpServer + >::VALUE || ::flame_ide::ComparingTypes::VALUE + || ::flame_ide::ComparingTypes::VALUE +>; + +template +using IsClient = ::flame_ide::IntegralConstant< + bool + , ::flame_ide::ComparingTypes< + EndpointType, ::flame_ide::os::network::UdpClient + >::VALUE || ::flame_ide::ComparingTypes::VALUE + || ::flame_ide::ComparingTypes::VALUE +>; + +template +using IsCommonEndpoint = ::flame_ide::IntegralConstant< + bool, IsServer::VALUE || IsClient::VALUE +>; + +template +using IsEndpointProcessor = ::flame_ide::IntegralConstant< + bool + , ::flame_ide::ComparingTypes::VALUE + || ::flame_ide::ComparingTypes::VALUE +>; + +template +using IsHandlerEndpoint = ::flame_ide::IntegralConstant< + bool, ::flame_ide::ComparingTypes::VALUE + || ::flame_ide::ComparingTypes::VALUE +>; +template +using IsOsEndpoint = ::flame_ide::IntegralConstant< + bool + , ::flame_ide::ComparingTypes::VALUE + || ::flame_ide::ComparingTypes::VALUE +>; + +// Mappers + +// Gets os::network::{ UdpServer, UdpClient } <-> { Server, Client } +template +using EndpointTypeMapper = ::flame_ide::TypeMapper< + EndpointType + , typename ::flame_ide::ChooseType< + IsServer::VALUE, ServerMatchingTrait, ClientMatchingTrait + >::Type +>; + +template< + typename HandlerEndpoint + , typename = typename ::flame_ide::EnableType< + IsHandlerEndpoint::VALUE || IsEndpointProcessor::VALUE, HandlerEndpoint + >::Type +> +using HandlerEndpointDataMapper = ::flame_ide::TypeMapper< + HandlerEndpoint + , typename ::flame_ide::ChooseType< + IsServer::VALUE + , typename ::flame_ide::ChooseType< + IsHandlerEndpoint::VALUE + , ServerDataMatchingTrait + , ServerProcessorMatchingTrait + >::Type + , typename ::flame_ide::ChooseType< + IsHandlerEndpoint::VALUE + , ClientDataMatchingTrait + , ClientProcessorMatchingTrait + >::Type + >::Type +>; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_TYPE_MAPPING_HPP diff --git a/src/Handler/Network/Udp/Types.hpp b/src/Handler/Network/Udp/Types.hpp new file mode 100644 index 00000000..846530b2 --- /dev/null +++ b/src/Handler/Network/Udp/Types.hpp @@ -0,0 +1,37 @@ +#ifndef HANDLER_INTERNAL_UDP_TYPES_HPP +#define HANDLER_INTERNAL_UDP_TYPES_HPP + +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +enum class MessageState +{ + EMPTY + , PROCESSING + , READY +}; + +template +struct HandlerEndpointUdpData +{ + templates::UniquePointer container = decltype(container)::makeEmpty(); + os::threads::Spin spin; +}; + +}}}} // namespace flame_ide::handler::network::udp + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_TYPES_HPP diff --git a/src/Handler/Network/Udp/Workers.cpp b/src/Handler/Network/Udp/Workers.cpp new file mode 100644 index 00000000..a81a847e --- /dev/null +++ b/src/Handler/Network/Udp/Workers.cpp @@ -0,0 +1,68 @@ +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +// + +ServerWorker::ServerWorker(Handler::Udp &udpInit) noexcept + : udp{ udpInit } +{} + +void ServerWorker::processing() noexcept +{ + auto event = os::async::network::Registrar{}.popUdpServer(); + if (event == decltype(event){}) + return; + udp.process(*this, event); +} + +// + +ClientWorker::ClientWorker(Handler::Udp &udpInit) noexcept + : udp{ udpInit } +{} + +void ClientWorker::processing() noexcept +{ + auto event = os::async::network::Registrar{}.popUdpClient(); + if (event == decltype(event){}) + return; + udp.process(*this, event); +} + +// + +Workers::Workers(Handler::Udp &udpInit) noexcept + : serverWorker{ udpInit }, clientWorker{ udpInit } +{} + +void Workers::start() noexcept +{ + serverWorker.start(); + clientWorker.start(); +} + +void Workers::stop() noexcept +{ + serverWorker.stop(); + clientWorker.stop(); +} + +WorkerBase::Notifier Workers::serverNotifier() noexcept +{ + return serverWorker.notifier(); +} +WorkerBase::Notifier Workers::clientNotifier() noexcept +{ + return clientWorker.notifier(); +} + + +}}}} // namespace flame_ide::handler::network::udp diff --git a/src/Handler/Network/Udp/Workers.hpp b/src/Handler/Network/Udp/Workers.hpp new file mode 100644 index 00000000..e80b813f --- /dev/null +++ b/src/Handler/Network/Udp/Workers.hpp @@ -0,0 +1,63 @@ +#ifndef HANDLER_INTERNAL_UDP_WORKERS_HPP +#define HANDLER_INTERNAL_UDP_WORKERS_HPP + +#include +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{ + +// + +class ServerWorker: public WorkerBase, private ServerProcessor +{ +public: + ServerWorker(Handler::Udp &udpInit) noexcept; + +private: + void processing() noexcept override; + +private: + Handler::Udp &udp; +}; + +// + +class ClientWorker: public WorkerBase, private ClientProcessor +{ +public: + ClientWorker(Handler::Udp &udpInit) noexcept; + +private: + void processing() noexcept override; + +private: + Handler::Udp &udp; +}; + +// + +class Workers +{ +public: + Workers(Handler::Udp &udpInit) noexcept; + + void start() noexcept; + void stop() noexcept; + + WorkerBase::Notifier serverNotifier() noexcept; + WorkerBase::Notifier clientNotifier() noexcept; + +private: + ServerWorker serverWorker; + ClientWorker clientWorker; +}; + +}}}} // namespace flame_ide::handler::network::udp + +#endif // HANDLER_INTERNAL_UDP_WORKERS_HPP diff --git a/src/Handler/Network/WorkerBase.cpp b/src/Handler/Network/WorkerBase.cpp new file mode 100644 index 00000000..4713fcd2 --- /dev/null +++ b/src/Handler/Network/WorkerBase.cpp @@ -0,0 +1,64 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +WorkerBase::Notifier WorkerBase::notifier() noexcept +{ + return WorkerBase::Notifier{ condvar }; +} + +os::Status WorkerBase::start() noexcept +{ + run(); + return getStatus(); + +} + +os::Status WorkerBase::stop() noexcept +{ + { + os::threads::Locker locker{ stopSpin }; + stopFlag = true; + } + + if (condvar.isWait()) + condvar.notify(); + + // join(); + return getStatus(); +} + +void WorkerBase::vRun() noexcept +{ + while (!needStop()) + { + condvar.wait(); + + if (needStop()) + break; + + processing(); + } +} + +bool WorkerBase::needStop() noexcept +{ + os::threads::Locker locker{ stopSpin }; + return stopFlag; +} + +// + +WorkerBase::Notifier::Notifier(os::threads::ConditionVariable &condvarInit) noexcept + : condvar{ &condvarInit } +{} + +void WorkerBase::Notifier::operator()() noexcept +{ + condvar->notify(); +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/WorkerBase.hpp b/src/Handler/Network/WorkerBase.hpp new file mode 100644 index 00000000..a6d92bbe --- /dev/null +++ b/src/Handler/Network/WorkerBase.hpp @@ -0,0 +1,82 @@ +#ifndef HANDLER_INTERNAL_WORKER_BASE_HPP +#define HANDLER_INTERNAL_WORKER_BASE_HPP + +#include +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +class WorkerBase: private os::threads::ThreadBase +{ + using Parent = os::threads::ThreadBase; + friend Parent; + +public: + class Notifier: public ::flame_ide::DefaultFunctorBase + { + public: + Notifier(const WorkerBase::Notifier &) = default; + Notifier(WorkerBase::Notifier &&) = default; + Notifier(os::threads::ConditionVariable &condvar) noexcept; + + Notifier &operator=(const WorkerBase::Notifier &) = default; + Notifier &operator=(WorkerBase::Notifier &&) = default; + + virtual void operator()() noexcept override; + + private: + Notifier() = default; + + private: + os::threads::ConditionVariable *condvar; + }; + +public: + using Parent::getStatus; + + /// + /// @brief getNotifier + /// @return + /// + Notifier notifier() noexcept; + + /// + /// @brief start + /// @return + /// + os::Status start() noexcept; + + /// + /// @brief stop + /// @return + /// + os::Status stop() noexcept; + +protected: + virtual void processing() noexcept = 0; + + bool needStop() noexcept; + +private: + virtual void vRun() noexcept override; + + +private: + os::threads::Mutex mutex; + os::threads::ConditionVariable condvar{ mutex }; + + os::threads::Spin stopSpin; + bool stopFlag = false; +}; + +// + + +}}} // namespace flame_ide::handler::network + +#endif // HANDLER_INTERNAL_WORKER_BASE_HPP diff --git a/src/Handler/Network/Workers.cpp b/src/Handler/Network/Workers.cpp new file mode 100644 index 00000000..18591ad1 --- /dev/null +++ b/src/Handler/Network/Workers.cpp @@ -0,0 +1,33 @@ +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +Workers::Workers(Handler::Udp &udp) noexcept : udpWorkers{ udp } +{} + +Workers::~Workers() noexcept +{ + stop(); +} + +void Workers::start() noexcept +{ + udpWorkers.start(); +} + +void Workers::stop() noexcept +{ + udpWorkers.stop(); +} + +udp::Workers &Workers::udp() noexcept +{ + return udpWorkers; +} + +}}} // namespace flame_ide::handler::network diff --git a/src/Handler/Network/Workers.hpp b/src/Handler/Network/Workers.hpp new file mode 100644 index 00000000..7546e1aa --- /dev/null +++ b/src/Handler/Network/Workers.hpp @@ -0,0 +1,43 @@ +#ifndef HANDLER_INTERNAL_WORKERS_HPP +#define HANDLER_INTERNAL_WORKERS_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{ + +class Workers +{ +public: + Workers(Handler::Udp &udp) noexcept; + ~Workers() noexcept; + + /// + /// @brief start + /// @return + /// + // TODO + void start() noexcept; + + /// + /// @brief stop + /// @return + /// + // TODO + void stop() noexcept; + + /// + /// \brief udp + /// \return + /// + udp::Workers &udp() noexcept; + +private: + udp::Workers udpWorkers; +}; + +}}} // namespace flame_ide::handler::network + +#endif // HANDLER_INTERNAL_WORKERS_HPP diff --git a/src/Handler/Tests/CMakeLists.txt b/src/Handler/Tests/CMakeLists.txt new file mode 100644 index 00000000..d8bd9460 --- /dev/null +++ b/src/Handler/Tests/CMakeLists.txt @@ -0,0 +1,115 @@ +cmake_minimum_required(VERSION 3.14) + +if(NOT FLAME_TESTING) + return() +endif() + +set(NAME "Handler.Tests") +set(NAME_ALIAS "Handler::Tests") +set(INCLUDE_PATHS + ${FLAME_INCLUDE_PATH} + ${FLAME_INCLUDE_TEST_PATH} +) +get_sources(FILE_LIST) +list(FILTER FILE_LIST EXCLUDE REGEX "main.cpp") + +set(DEPENDENCY_HEADER_TARGETS + # "${FLAME_NAMESPACE}::Handler::Headers" + "${FLAME_NAMESPACE}::Handler::Network::Headers" +) + +set(STATIC_ALIAS_NAME "${FLAME_NAMESPACE}::${NAME_ALIAS}::Static") +set(SHARED_ALIAS_NAME "${FLAME_NAMESPACE}::${NAME_ALIAS}::Shared") + +set(DEPEND_OBJECTS + "${FLAME_NAMESPACE}::Handler::Network::Test::Object" + "${FLAME_NAMESPACE}::Handler::Network::Udp::Test::Object" + "${FLAME_NAMESPACE}::Handler::Network::Tcp::Test::Object" +) +set(INDEPEND_OBJECTS + "${FLAME_NAMESPACE}::Handler::Network::Test::Object::Independ" + "${FLAME_NAMESPACE}::Handler::Network::Udp::Test::Object::Independ" + "${FLAME_NAMESPACE}::Handler::Network::Tcp::Test::Object::Independ" +) + +set(MAIN_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp") +if(FLAME_MAKE_STATIC) + set(MAKE_STATIC MAKE_STATIC) + flame_compile_binary( + NAME "${NAME}.static" + SOURCE_LIST "${MAIN_SOURCE}" + #INSTALL_PATH + INCLUDE_PATHS "${INCLUDE_PATHS}" + #HEADER_LIST + #COMMPILE_FLAGS + #LINK_FLAGS" + DEPENDENCY_TARGET_LIST "${STATIC_ALIAS_NAME}" + DEFINES "${SHARED_LIBRARY_DIR_DEFINE}" + + NO_RTTI + EXCEPTIONS + + TEST + TEST_ARGUMENTS "" + ) +endif() +if(FLAME_MAKE_SHARED) + set(MAKE_SHARED MAKE_SHARED) + flame_compile_binary( + NAME "${NAME}.shared" + SOURCE_LIST "${MAIN_SOURCE}" + #INSTALL_PATH + INCLUDE_PATHS "${INCLUDE_PATHS}" + #HEADER_LIST + #COMMPILE_FLAGS" + #LINK_FLAGS" + DEPENDENCY_TARGET_LIST "${STATIC_ALIAS_NAME}" + DEFINES "${SHARED_LIBRARY_DIR_DEFINE}" + + NO_RTTI + EXCEPTIONS + + TEST + TEST_ARGUMENTS "" + ) +endif() + +set(DEPENDENCY_TARGETS_FOR_STATIC + "${FLAME_NAMESPACE}::Handler::Network::Static" + "${FLAME_NAMESPACE}::Os::Static" + "${DEPEND_OBJECTS}" +) +set(DEPENDENCY_TARGETS_FOR_SHARED + "${FLAME_NAMESPACE}::Handler::Network::Shared" + "${FLAME_NAMESPACE}::Os::Shared" + "${INDEPEND_OBJECTS}" +) +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + DEPENDENCY_TARGETS_FOR_STATIC "${DEPENDENCY_TARGETS_FOR_STATIC}" + DEPENDENCY_TARGETS_FOR_SHARED "${DEPENDENCY_TARGETS_FOR_SHARED}" + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + STATIC_ALIAS_NAME "${STATIC_ALIAS_NAME}" + SHARED_ALIAS_NAME "${SHARED_ALIAS_NAME}" + + DEFINES "${SHARED_LIBRARY_DIR_DEFINE}" + + NO_RTTI + EXCEPTIONS + + ${MAKE_STATIC} + ${MAKE_SHARED} +) + +set(SOURCE_MODULES + ${CMAKE_CURRENT_LIST_DIR}/Network +) +foreach(module ${SOURCE_MODULES}) + add_subdirectory(${module}) +endforeach() diff --git a/src/Handler/Tests/Network/CMakeLists.txt b/src/Handler/Tests/Network/CMakeLists.txt new file mode 100644 index 00000000..c3a1fe1f --- /dev/null +++ b/src/Handler/Tests/Network/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.14) + +if(NOT FLAME_TESTING) + return() +endif() + +set(NAME "Handler.Network.Test") +set(NAME_ALIAS "Handler::Network::Test") + +get_sources(FILE_LIST) + +set(DEPENDENCY_HEADER_TARGETS + "${FLAME_NAMESPACE}::Handler::Network::Headers" +) + +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${CMAKE_BINARY_DIR}/generated/include" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + + NO_RTTI + EXCEPTIONS +) + +set(SOURCE_MODULES + ${CMAKE_CURRENT_LIST_DIR}/Udp + ${CMAKE_CURRENT_LIST_DIR}/Tcp +) +foreach(module ${SOURCE_MODULES}) + add_subdirectory(${module}) +endforeach() diff --git a/src/Handler/Tests/Network/HandlerTest.cpp b/src/Handler/Tests/Network/HandlerTest.cpp new file mode 100644 index 00000000..7c994ba8 --- /dev/null +++ b/src/Handler/Tests/Network/HandlerTest.cpp @@ -0,0 +1,216 @@ +#include +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +HandlerTest::HandlerTest() : ::AbstractTest("Handler") +{} + +HandlerTest::~HandlerTest() = default; + +int HandlerTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "initialization" + , [this]() { return init(); } + )); + + // UPD + // Server + CHECK_RESULT_SUCCESS(doTestCase( + "UDP Server push-pop" + , [this]() { return udpServerPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "UDP Server communication" + , [this]() { return udpServerCommunicate(); } + )); + // Client + CHECK_RESULT_SUCCESS(doTestCase( + "UDP Client push-pop" + , [this]() { return udpClientPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "UDP Client communication" + , [this]() { return udpClientCommunicate(); } + )); + + // TCP + // Server + CHECK_RESULT_SUCCESS(doTestCase( + "TCP Server push-pop" + , [this]() { return tcpServerPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "TCP Server communication" + , [this]() { return tcpServerCommunicate(); } + )); + // Client + CHECK_RESULT_SUCCESS(doTestCase( + "TCP Client push-pop" + , [this]() { return tcpClientPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "TCP Client communication" + , [this]() { return tcpClientCommunicate(); } + )); + + return ResultType::SUCCESS; +} + +int HandlerTest::init() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::udpServerPushPop() +{ + flame_ide::os::network::UdpServer originalUdpServer{ 65001 }; + const flame_ide::os::Socket originalNativeSocket = originalUdpServer.native(); + + Handler handler; + Handler::ExpectedServerHandle updServerHandle = + handler.pushUdp(::flame_ide::move(originalUdpServer)); + + // Check valid handle + { + ResultType pushResult = ResultType::FAILED; + updServerHandle.ifResultGet( + [&pushResult](auto &) + { + pushResult = ResultType::SUCCESS; + } + ); + IN_CASE_CHECK(pushResult == ResultType::SUCCESS); + } + + // Get handle + Handler::ServerHandle serverHandle; + updServerHandle.ifResult( + [&serverHandle](Handler::ServerHandle &&inputHandle) + { + serverHandle = move(inputHandle); + } + ); + Handler::ExpectedUdpServer udpServer = handler.popUdp(serverHandle); + + // Check valid server + { + ResultType popResult = ResultType::FAILED; + udpServer.ifResultGet( + [&popResult](auto &) + { + popResult = ResultType::SUCCESS; + } + ); + IN_CASE_CHECK(popResult == ResultType::SUCCESS); + } + + // Check valid descriptor + flame_ide::os::network::UdpServer popedUdpServer; + udpServer.ifResult( + [&popedUdpServer](os::network::UdpServer &&inputServer) + { + popedUdpServer = move(inputServer); + } + ); + const flame_ide::os::Socket popedNativeSocket = popedUdpServer.native(); + IN_CASE_CHECK_END(popedNativeSocket.descriptor == originalNativeSocket.descriptor); +} + +int HandlerTest::udpServerCommunicate() +{ + const auto port = ::flame_ide::os::network::Ipv4::Port{ 65001 }; + const auto ip = ::flame_ide::os::network::Ipv4::localhost(port); + + ::flame_ide::os::network::UdpClient udpClient{ ip }; + + ::flame_ide::os::network::UdpServer originalUdpServer{ port }; + Handler handler; + Handler::ExpectedServerHandle updServerHandle = + handler.pushUdp(::flame_ide::move(originalUdpServer)); + + // Check valid handle + { + ResultType pushResult = ResultType::FAILED; + updServerHandle.ifResultGet( + [&pushResult](auto &) + { + pushResult = ResultType::SUCCESS; + } + ); + IN_CASE_CHECK(pushResult == ResultType::SUCCESS); + } + + Handler::ServerHandle serverHandle; + updServerHandle.ifResult( + [&serverHandle](Handler::ServerHandle &&inputHandle) + { + serverHandle = move(inputHandle); + } + ); + + // TODO: communicate a-la pingPong test in UdpTest + + return ResultType::SUCCESS; +} + +int HandlerTest::udpClientPushPop() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::udpClientCommunicate() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::tcpServerPushPop() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::tcpServerCommunicate() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::tcpClientPushPop() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +int HandlerTest::tcpClientCommunicate() +{ + Handler handler; + flame_ide::unused(handler); + + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/HandlerTest.hpp b/src/Handler/Tests/Network/HandlerTest.hpp new file mode 100644 index 00000000..9848d192 --- /dev/null +++ b/src/Handler/Tests/Network/HandlerTest.hpp @@ -0,0 +1,38 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_HANDLER_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_HANDLER_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class HandlerTest: public ::AbstractTest +{ +public: + HandlerTest(); + virtual ~HandlerTest(); + +private: + virtual int vStart(); + + int init(); + + int udpServerPushPop(); + int udpServerCommunicate(); + + int udpClientPushPop(); + int udpClientCommunicate(); + + int tcpServerPushPop(); + int tcpServerCommunicate(); + + int tcpClientPushPop(); + int tcpClientCommunicate(); +}; + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_HANDLER_TEST_HPP diff --git a/src/Handler/Tests/Network/InternalTest.cpp b/src/Handler/Tests/Network/InternalTest.cpp new file mode 100644 index 00000000..424ea0b5 --- /dev/null +++ b/src/Handler/Tests/Network/InternalTest.cpp @@ -0,0 +1,20 @@ +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +InternalTest::InternalTest() : ::AbstractTest("Internal") +{} + +InternalTest::~InternalTest() = default; + +int InternalTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/InternalTest.hpp b/src/Handler/Tests/Network/InternalTest.hpp new file mode 100644 index 00000000..913805c2 --- /dev/null +++ b/src/Handler/Tests/Network/InternalTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_INTERNAL_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_INTERNAL_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class InternalTest: public ::AbstractTest +{ +public: + InternalTest(); + virtual ~InternalTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_INTERNAL_TEST_HPP diff --git a/src/Handler/Tests/Network/NotificatorsTest.cpp b/src/Handler/Tests/Network/NotificatorsTest.cpp new file mode 100644 index 00000000..8684a978 --- /dev/null +++ b/src/Handler/Tests/Network/NotificatorsTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +NotificatorsTest::NotificatorsTest() : ::AbstractTest("Notificators") +{} + +NotificatorsTest::~NotificatorsTest() = default; + +int NotificatorsTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/NotificatorsTest.hpp b/src/Handler/Tests/Network/NotificatorsTest.hpp new file mode 100644 index 00000000..4e09363e --- /dev/null +++ b/src/Handler/Tests/Network/NotificatorsTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_NOTIFICATORS_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_NOTIFICATORS_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class NotificatorsTest: public ::AbstractTest +{ +public: + NotificatorsTest(); + virtual ~NotificatorsTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_NOTIFICATORS_TEST_HPP diff --git a/src/Handler/Tests/Network/ServerHandleTest.cpp b/src/Handler/Tests/Network/ServerHandleTest.cpp new file mode 100644 index 00000000..8bfd9773 --- /dev/null +++ b/src/Handler/Tests/Network/ServerHandleTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +ServerHandleTest::ServerHandleTest() : ::AbstractTest("ServerHandle") +{} + +ServerHandleTest::~ServerHandleTest() = default; + +int ServerHandleTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/ServerHandleTest.hpp b/src/Handler/Tests/Network/ServerHandleTest.hpp new file mode 100644 index 00000000..c83a4797 --- /dev/null +++ b/src/Handler/Tests/Network/ServerHandleTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_SERVER_HANDLE_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_SERVER_HANDLE_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class ServerHandleTest: public ::AbstractTest +{ +public: + ServerHandleTest(); + virtual ~ServerHandleTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_SERVER_HANDLE_TEST_HPP diff --git a/src/Handler/Tests/Network/SessionHandleTest.cpp b/src/Handler/Tests/Network/SessionHandleTest.cpp new file mode 100644 index 00000000..46155f5b --- /dev/null +++ b/src/Handler/Tests/Network/SessionHandleTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +SessionHandleTest::SessionHandleTest() : ::AbstractTest("SessionHandle") +{} + +SessionHandleTest::~SessionHandleTest() = default; + +int SessionHandleTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/SessionHandleTest.hpp b/src/Handler/Tests/Network/SessionHandleTest.hpp new file mode 100644 index 00000000..56d1677b --- /dev/null +++ b/src/Handler/Tests/Network/SessionHandleTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_SESSION_HANDLE_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_SESSION_HANDLE_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class SessionHandleTest: public ::AbstractTest +{ +public: + SessionHandleTest(); + virtual ~SessionHandleTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_SESSION_HANDLE_TEST_HPP diff --git a/src/Handler/Tests/Network/Sources.cmake b/src/Handler/Tests/Network/Sources.cmake new file mode 100644 index 00000000..163cc0c9 --- /dev/null +++ b/src/Handler/Tests/Network/Sources.cmake @@ -0,0 +1,20 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/HandlerTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/HandlerTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/InternalTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/InternalTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/NotificatorsTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NotificatorsTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerHandleTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerHandleTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/SessionHandleTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SessionHandleTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/TcpTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TcpTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/UdpTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UdpTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkerBaseTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkerBaseTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkersTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkersTest.hpp +) diff --git a/src/Handler/Tests/Network/Tcp/CMakeLists.txt b/src/Handler/Tests/Network/Tcp/CMakeLists.txt new file mode 100644 index 00000000..7b5b7e3a --- /dev/null +++ b/src/Handler/Tests/Network/Tcp/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.14) + +if(NOT FLAME_TESTING) + return() +endif() + +set(NAME "Handler.Network.Tcp.Test") +set(NAME_ALIAS "Handler::Network::Tcp::Test") + +get_sources(FILE_LIST) + +set(DEPENDENCY_HEADER_TARGETS + "${FLAME_NAMESPACE}::Handler::Network::Headers" +) + +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${CMAKE_BINARY_DIR}/generated/include" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + + NO_RTTI + EXCEPTIONS +) diff --git a/src/Handler/Tests/Network/Tcp/QueueTest.cpp b/src/Handler/Tests/Network/Tcp/QueueTest.cpp new file mode 100644 index 00000000..f9488c6d --- /dev/null +++ b/src/Handler/Tests/Network/Tcp/QueueTest.cpp @@ -0,0 +1,53 @@ +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{namespace tests +{ + +QueueTest::QueueTest() : ::AbstractTest("tcp::Queue") +{} + +QueueTest::~QueueTest() = default; + +int QueueTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "initialization" + , [this]() { return init(); } + + )); + CHECK_RESULT_SUCCESS(doTestCase( + "server push-pop" + , [this]() { return serverPushPop(); } + + )); + return ResultType::SUCCESS; +} + +int QueueTest::init() +{ + tcp::Tcp tcp; + return ResultType::SUCCESS; +} + +int QueueTest::serverPushPop() +{ + tcp::Tcp tcp; + os::network::TcpServer server{ 65001 }; + + const os::Socket expectedSocket = server.native(); + + auto handle = tcp.push(flame_ide::move(server)); + IN_CASE_CHECK(handle != nullptr); + + auto resultServer = tcp.pop(handle); + IN_CASE_CHECK(expectedSocket.descriptor == resultServer.native().descriptor); + + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::tcp::tests diff --git a/src/Handler/Tests/Network/Tcp/QueueTest.hpp b/src/Handler/Tests/Network/Tcp/QueueTest.hpp new file mode 100644 index 00000000..0af5c9ef --- /dev/null +++ b/src/Handler/Tests/Network/Tcp/QueueTest.hpp @@ -0,0 +1,29 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_TCPTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_TCPTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tcp +{namespace tests +{ + +class QueueTest: public ::AbstractTest +{ +public: + QueueTest(); + virtual ~QueueTest(); + +private: + virtual int vStart(); + +private: + int init(); + int serverPushPop(); +}; + +}}}}} // namespace flame_ide::handler::network::tcp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_TCPTEST_HPP diff --git a/src/Handler/Tests/Network/Tcp/Sources.cmake b/src/Handler/Tests/Network/Tcp/Sources.cmake new file mode 100644 index 00000000..e004d959 --- /dev/null +++ b/src/Handler/Tests/Network/Tcp/Sources.cmake @@ -0,0 +1,4 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/QueueTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/QueueTest.hpp +) diff --git a/src/Handler/Tests/Network/TcpTest.cpp b/src/Handler/Tests/Network/TcpTest.cpp new file mode 100644 index 00000000..067a531f --- /dev/null +++ b/src/Handler/Tests/Network/TcpTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +TcpTest::TcpTest() : ::AbstractTest("Tcp") +{} + +TcpTest::~TcpTest() = default; + +int TcpTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/TcpTest.hpp b/src/Handler/Tests/Network/TcpTest.hpp new file mode 100644 index 00000000..a3307507 --- /dev/null +++ b/src/Handler/Tests/Network/TcpTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_TCP_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_TCP_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class TcpTest: public ::AbstractTest +{ +public: + TcpTest(); + virtual ~TcpTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_TCP_TEST_HPP diff --git a/src/Handler/Tests/Network/Udp/ActualDataTest.cpp b/src/Handler/Tests/Network/Udp/ActualDataTest.cpp new file mode 100644 index 00000000..15140b49 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ActualDataTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +ActualDataTest::ActualDataTest() : ::AbstractTest("udp::ActualData") +{} + +ActualDataTest::~ActualDataTest() = default; + +int ActualDataTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/ActualDataTest.hpp b/src/Handler/Tests/Network/Udp/ActualDataTest.hpp new file mode 100644 index 00000000..7a64ca42 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ActualDataTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_ACTUALDATATEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_ACTUALDATATEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class ActualDataTest: public ::AbstractTest +{ +public: + ActualDataTest(); + virtual ~ActualDataTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_ACTUALDATATEST_HPP diff --git a/src/Handler/Tests/Network/Udp/CMakeLists.txt b/src/Handler/Tests/Network/Udp/CMakeLists.txt new file mode 100644 index 00000000..1e936626 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.14) + +if(NOT FLAME_TESTING) + return() +endif() + +set(NAME "Handler.Network.Udp.Test") +set(NAME_ALIAS "Handler::Network::Udp::Test") + +get_sources(FILE_LIST) + +set(DEPENDENCY_HEADER_TARGETS + "${FLAME_NAMESPACE}::Handler::Network::Headers" +) + +flame_compile_library( + NAME "${NAME}" + SOURCE_LIST "${FILE_LIST}" + INCLUDE_PATHS "${INCLUDE_PATHS}" "${CMAKE_BINARY_DIR}/generated/include" + DEPENDENCY_HEADER_TARGETS "${DEPENDENCY_HEADER_TARGETS}" + + OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object" + INDEPENDENT_OBJECT_ALIAS_NAME + "${FLAME_NAMESPACE}::${NAME_ALIAS}::Object::Independ" + + NO_RTTI + EXCEPTIONS +) diff --git a/src/Handler/Tests/Network/Udp/ClientTest.cpp b/src/Handler/Tests/Network/Udp/ClientTest.cpp new file mode 100644 index 00000000..46b0ec7f --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ClientTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +ClientTest::ClientTest() : ::AbstractTest("udp::Client") +{} + +ClientTest::~ClientTest() = default; + +int ClientTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/ClientTest.hpp b/src/Handler/Tests/Network/Udp/ClientTest.hpp new file mode 100644 index 00000000..a46eefc5 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ClientTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_CLIENTTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_CLIENTTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class ClientTest: public ::AbstractTest +{ +public: + ClientTest(); + virtual ~ClientTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_CLIENTTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/EndpointTest.cpp b/src/Handler/Tests/Network/Udp/EndpointTest.cpp new file mode 100644 index 00000000..ded4d8ae --- /dev/null +++ b/src/Handler/Tests/Network/Udp/EndpointTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +EndpointTest::EndpointTest() : ::AbstractTest("udp::Endpoint") +{} + +EndpointTest::~EndpointTest() = default; + +int EndpointTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/EndpointTest.hpp b/src/Handler/Tests/Network/Udp/EndpointTest.hpp new file mode 100644 index 00000000..3567bc64 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/EndpointTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_ENDPOINTTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_ENDPOINTTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class EndpointTest: public ::AbstractTest +{ +public: + EndpointTest(); + virtual ~EndpointTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_ENDPOINTUDP_TEST_HPP diff --git a/src/Handler/Tests/Network/Udp/NotificatorsTest.cpp b/src/Handler/Tests/Network/Udp/NotificatorsTest.cpp new file mode 100644 index 00000000..e0d0edc4 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/NotificatorsTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +NotificatorsTest::NotificatorsTest() : ::AbstractTest("udp::Notificators") +{} + +NotificatorsTest::~NotificatorsTest() = default; + +int NotificatorsTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/NotificatorsTest.hpp b/src/Handler/Tests/Network/Udp/NotificatorsTest.hpp new file mode 100644 index 00000000..684620b7 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/NotificatorsTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_NOTIFICATORSTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_NOTIFICATORSTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class NotificatorsTest: public ::AbstractTest +{ +public: + NotificatorsTest(); + virtual ~NotificatorsTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_NOTIFICATORSTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/ProcessingTest.cpp b/src/Handler/Tests/Network/Udp/ProcessingTest.cpp new file mode 100644 index 00000000..7dea9c71 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ProcessingTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +ProcessingTest::ProcessingTest() : ::AbstractTest("udp::Processing") +{} + +ProcessingTest::~ProcessingTest() = default; + +int ProcessingTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/ProcessingTest.hpp b/src/Handler/Tests/Network/Udp/ProcessingTest.hpp new file mode 100644 index 00000000..f76f59c5 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ProcessingTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_PROCESSINGTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_PROCESSINGTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class ProcessingTest: public ::AbstractTest +{ +public: + ProcessingTest(); + virtual ~ProcessingTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_PROCESSINGTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/ServerTest.cpp b/src/Handler/Tests/Network/Udp/ServerTest.cpp new file mode 100644 index 00000000..391bb77d --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ServerTest.cpp @@ -0,0 +1,35 @@ +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +ServerTest::ServerTest() : ::AbstractTest("udp::Server") +{} + +ServerTest::~ServerTest() = default; + +int ServerTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "initialization" + , [this]() { return init(); } + + )); + return ResultType::SUCCESS; +} + +int ServerTest::init() noexcept +{ + ServerCommunicationData server; + flame_ide::unused(server); + + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/ServerTest.hpp b/src/Handler/Tests/Network/Udp/ServerTest.hpp new file mode 100644 index 00000000..2f73d021 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/ServerTest.hpp @@ -0,0 +1,28 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_SERVERTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_SERVERTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class ServerTest: public ::AbstractTest +{ +public: + ServerTest(); + virtual ~ServerTest(); + +private: + virtual int vStart(); + +private: + int init() noexcept; +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_SERVERTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/Sources.cmake b/src/Handler/Tests/Network/Udp/Sources.cmake new file mode 100644 index 00000000..b4bb5ddd --- /dev/null +++ b/src/Handler/Tests/Network/Udp/Sources.cmake @@ -0,0 +1,22 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/ActualDataTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ActualDataTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ClientTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ClientTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/EndpointTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/EndpointTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/NotificatorsTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NotificatorsTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ProcessingTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ProcessingTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/StorageTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/StorageTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/TypeMappingTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TypeMappingTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/UdpTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UdpTest.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkersTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WorkersTest.hpp +) diff --git a/src/Handler/Tests/Network/Udp/StorageTest.cpp b/src/Handler/Tests/Network/Udp/StorageTest.cpp new file mode 100644 index 00000000..aa089837 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/StorageTest.cpp @@ -0,0 +1,114 @@ +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +StorageTest::StorageTest() : ::AbstractTest("udp::Storage") +{} + +StorageTest::~StorageTest() = default; + +int StorageTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "initialization" + , [this]() { return init(); } + )); + // + CHECK_RESULT_SUCCESS(doTestCase( + "server push-pop" + , [this]() { return serverPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "client push-pop" + , [this]() { return clientPushPop(); } + )); + // + CHECK_RESULT_SUCCESS(doTestCase( + "Max servers push-pop" + , [this]() { return maxServersPushPop(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Max clients push-pop" + , [this]() { return maxClientsPushPop(); } + )); + // + CHECK_RESULT_SUCCESS(doTestCase( + "Server process" + , [this]() { return processServer(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Client process" + , [this]() { return processClient(); } + )); + return ResultType::SUCCESS; +} + +int StorageTest::init() +{ + udp::Storage storage; + return ResultType::SUCCESS; +} + +int StorageTest::serverPushPop() +{ + udp::Storage storage; + os::network::UdpServer server{ 65001 }; + + const os::Socket expectedSocket = server.native(); + + auto handle = storage.push(flame_ide::move(server)); + IN_CASE_CHECK(handle.operator->() != nullptr); + + auto resultServer = storage.pop(handle); + IN_CASE_CHECK(expectedSocket.descriptor == resultServer.native().descriptor); + + return ResultType::SUCCESS; +} + +int StorageTest::clientPushPop() +{ + udp::Storage storage; + os::network::UdpClient client{ os::network::Ipv4::localhost(65001) }; + + const os::Socket expectedSocket = client.native(); + + auto handle = storage.push(flame_ide::move(client)); + IN_CASE_CHECK(handle.operator->() != nullptr); + + auto resultServer = storage.pop(handle); + IN_CASE_CHECK(expectedSocket.descriptor == resultServer.native().descriptor); + + return ResultType::SUCCESS; +} + +int StorageTest::maxServersPushPop() +{ + // Закинуть максимальное количество серверов + 1 + return ResultType::SUCCESS; +} + +int StorageTest::maxClientsPushPop() +{ + // Закинуть максимальное количество клиентов + 1 + return ResultType::SUCCESS; +} + +int StorageTest::processServer() +{ + // отладка ServerProcessor + return ResultType::SUCCESS; +} + +int StorageTest::processClient() +{ + // отладка ClientProcessor + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/StorageTest.hpp b/src/Handler/Tests/Network/Udp/StorageTest.hpp new file mode 100644 index 00000000..ba18b57b --- /dev/null +++ b/src/Handler/Tests/Network/Udp/StorageTest.hpp @@ -0,0 +1,37 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_STORAGETEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_STORAGETEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class StorageTest: public ::AbstractTest +{ +public: + StorageTest(); + virtual ~StorageTest(); + +private: + virtual int vStart(); + +private: + int init(); + + int serverPushPop(); + int clientPushPop(); + + int maxServersPushPop(); + int maxClientsPushPop(); + + int processServer(); + int processClient(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_STORAGETEST_HPP diff --git a/src/Handler/Tests/Network/Udp/TypeMappingTest.cpp b/src/Handler/Tests/Network/Udp/TypeMappingTest.cpp new file mode 100644 index 00000000..f72f7b2b --- /dev/null +++ b/src/Handler/Tests/Network/Udp/TypeMappingTest.cpp @@ -0,0 +1,129 @@ +#include + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +// EndpointTypeMapper + +static ::AbstractTest::ResultType serverEndpointTypeMapper() noexcept +{ + using ResultType = ::AbstractTest::ResultType; + + IN_CASE_CHECK(( + "Server -> os::network::UdpServer" + , ComparingTypes< + os::network::UdpServer + , EndpointTypeMapper::Type + >::VALUE + )); + + IN_CASE_CHECK_END(( + "os::network::UdpServer -> Server" + , ComparingTypes< + Server + , EndpointTypeMapper::Type + >::VALUE + )); +} + +static ::AbstractTest::ResultType clientEndpointTypeMapper() noexcept +{ + using ResultType = ::AbstractTest::ResultType; + + IN_CASE_CHECK(( + "Client -> os::network::UdpClient" + , ComparingTypes< + os::network::UdpClient + , EndpointTypeMapper::Type + >::VALUE + )); + IN_CASE_CHECK_END(( + "os::network::UdpClient -> Client" + , ComparingTypes< + Client + , EndpointTypeMapper::Type + >::VALUE + )); +} + +// HandlerEndpointDataMapper + +static ::AbstractTest::ResultType serverHandlerEndpointDataMapper() noexcept +{ + using ResultType = ::AbstractTest::ResultType; + + IN_CASE_CHECK(( + "Server -> HandlerEndpointUdpData" + , ComparingTypes< + HandlerEndpointUdpData + , HandlerEndpointDataMapper::Type + >::VALUE + )); + IN_CASE_CHECK_END(( + "ServerProcessor -> HandlerEndpointUdpData" + , ComparingTypes< + HandlerEndpointUdpData + , HandlerEndpointDataMapper::Type + >::VALUE + )); +} + +static ::AbstractTest::ResultType clientHandlerEndpointDataMapper() noexcept +{ + using ResultType = ::AbstractTest::ResultType; + + IN_CASE_CHECK(( + "Client -> HandlerEndpointUdpData" + , ComparingTypes< + HandlerEndpointUdpData + , HandlerEndpointDataMapper::Type + >::VALUE + )); + IN_CASE_CHECK_END(( + "ClientProcessor -> HandlerEndpointUdpData" + , ComparingTypes< + HandlerEndpointUdpData + , HandlerEndpointDataMapper::Type + >::VALUE + )); +} + +// + +TypeMappingTest::TypeMappingTest() : ::AbstractTest("udp::TypeMapping") +{} + +TypeMappingTest::~TypeMappingTest() = default; + +int TypeMappingTest::vStart() +{ + // + CHECK_RESULT_SUCCESS(doTestCase( + "Server <--> os::network::UdpServer" + , []() { return serverEndpointTypeMapper(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Client <--> os::network::UdpClient" + , []() { return clientEndpointTypeMapper(); } + )); + + // + CHECK_RESULT_SUCCESS(doTestCase( + "Server, ServerProcessor --> HandlerEndpointUdpData" + , []() { return serverHandlerEndpointDataMapper(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Client, ClientProcessor --> HandlerEndpointUdpData" + , []() { return clientHandlerEndpointDataMapper(); } + )); + + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/TypeMappingTest.hpp b/src/Handler/Tests/Network/Udp/TypeMappingTest.hpp new file mode 100644 index 00000000..b706088a --- /dev/null +++ b/src/Handler/Tests/Network/Udp/TypeMappingTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TYPEMAPPINGTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TYPEMAPPINGTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class TypeMappingTest: public ::AbstractTest +{ +public: + TypeMappingTest(); + virtual ~TypeMappingTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TYPEMAPPINGTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/UdpTest.cpp b/src/Handler/Tests/Network/Udp/UdpTest.cpp new file mode 100644 index 00000000..7edda20d --- /dev/null +++ b/src/Handler/Tests/Network/Udp/UdpTest.cpp @@ -0,0 +1,198 @@ +#include + +#include + +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +using Udp = Handler::Udp; + +UdpTest::UdpTest() : ::AbstractTest("udp::Udp") +{} + +UdpTest::~UdpTest() = default; + +int UdpTest::vStart() +{ + CHECK_RESULT_SUCCESS(doTestCase( + "Initialization" + , [this]() { return init(); } + )); + + CHECK_RESULT_SUCCESS(doTestCase( + "Push & pop server" + , [this]() { return pushPopServer(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Push server" + , [this]() { return pushServer(); } + )); + + CHECK_RESULT_SUCCESS(doTestCase( + "Push & pop client" + , [this]() { return pushPopClient(); } + )); + CHECK_RESULT_SUCCESS(doTestCase( + "Push client" + , [this]() { return pushClient(); } + )); + + return ResultType::SUCCESS; +} + +int UdpTest::init() noexcept +{ + Udp storage; + flame_ide::unused(storage); + + return ResultType::SUCCESS; +} + +int UdpTest::pushPopServer() noexcept +{ + os::network::UdpServer server{ 65001 }; + const os::Socket expectedSocket = server.native(); + IN_CASE_CHECK(expectedSocket.descriptor != os::SOCKET_INVALID.descriptor); + + Udp storage; + Handler::ExpectedServerHandle expectedHandle = storage.push(flame_ide::move(server)); + Handler::ServerHandle handle; + bool isError = false; + expectedHandle.ifResult( + [&handle](Handler::ServerHandle &&result) + { + handle = flame_ide::move(result); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + // IN_CASE_CHECK(handle.operator bool()); // handle.callbackDeregistrate == nullptr + + Handler::ExpectedUdpServer expectedServer = storage.pop(handle); + os::network::UdpServer resultServer; + expectedServer.ifResult( + [&resultServer](os::network::UdpServer &&server) + { + resultServer = flame_ide::move(server); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + IN_CASE_CHECK(expectedSocket.descriptor == resultServer.native().descriptor); + + return ResultType::SUCCESS; +} + +int UdpTest::pushServer() noexcept +{ + os::network::UdpServer server{ 65001 }; + IN_CASE_CHECK(server.native().descriptor != os::SOCKET_INVALID.descriptor); + + Udp storage; + Handler::ExpectedServerHandle expectedHandle = storage.push(flame_ide::move(server)); + Handler::ServerHandle handle; + bool isError = false; + expectedHandle.ifResult( + [&handle](Handler::ServerHandle &&result) + { + handle = flame_ide::move(result); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + // IN_CASE_CHECK(handle.operator bool()); // handle.callbackDeregistrate == nullptr + + return ResultType::SUCCESS; +} + +int UdpTest::pushPopClient() noexcept +{ + const os::network::Ipv4 ip{ { 127, 0, 0, 1 }, 65001 }; + os::network::UdpClient client{ ip }; + const os::Socket expectedSocket = client.native(); + IN_CASE_CHECK(expectedSocket.descriptor != os::SOCKET_INVALID.descriptor); + + Udp storage; + Handler::ExpectedSessionHandle expectedHandle = storage.push(flame_ide::move(client)); + Handler::SessionHandle handle; + bool isError = false; + expectedHandle.ifResult( + [&handle](Handler::SessionHandle &&result) + { + handle = flame_ide::move(result); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + // IN_CASE_CHECK(handle.operator bool()); // handle.callbackDeregistrate == nullptr + + Handler::ExpectedUdpClient expectedClient = storage.pop(handle); + os::network::UdpClient resultClient; + expectedClient.ifResult( + [&resultClient](os::network::UdpClient &&client) + { + resultClient = flame_ide::move(client); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + IN_CASE_CHECK(expectedSocket.descriptor == resultClient.native().descriptor); + + return ResultType::SUCCESS; +} + +int UdpTest::pushClient() noexcept +{ + const os::network::Ipv4 ip{ { 127, 0, 0, 1 }, 65001 }; + os::network::UdpClient client{ ip }; + IN_CASE_CHECK(client.native().descriptor != os::SOCKET_INVALID.descriptor); + + Udp storage; + Handler::ExpectedSessionHandle expectedHandle = storage.push(flame_ide::move(client)); + Handler::SessionHandle handle; + bool isError = false; + expectedHandle.ifResult( + [&handle](Handler::SessionHandle &&result) + { + handle = flame_ide::move(result); + } + ).ifError( + [&isError](os::Status &&) + { + isError = true; + } + ); + IN_CASE_CHECK(isError == false); + // IN_CASE_CHECK(handle.operator bool()); // handle.callbackDeregistrate == nullptr + + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/UdpTest.hpp b/src/Handler/Tests/Network/Udp/UdpTest.hpp new file mode 100644 index 00000000..dedfa0f0 --- /dev/null +++ b/src/Handler/Tests/Network/Udp/UdpTest.hpp @@ -0,0 +1,33 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_UDPTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_UDPTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class UdpTest: public ::AbstractTest +{ +public: + UdpTest(); + virtual ~UdpTest(); + +private: + virtual int vStart(); + + int init() noexcept; + + int pushPopServer() noexcept; + int pushServer() noexcept; + + int pushPopClient() noexcept; + int pushClient() noexcept; +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDPTEST_HPP diff --git a/src/Handler/Tests/Network/Udp/WorkersTest.cpp b/src/Handler/Tests/Network/Udp/WorkersTest.cpp new file mode 100644 index 00000000..9018395a --- /dev/null +++ b/src/Handler/Tests/Network/Udp/WorkersTest.cpp @@ -0,0 +1,20 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +WorkersTest::WorkersTest() : ::AbstractTest("udp::Workers") +{} + +WorkersTest::~WorkersTest() = default; + +int WorkersTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}}} // namespace flame_ide::handler::network::udp::tests diff --git a/src/Handler/Tests/Network/Udp/WorkersTest.hpp b/src/Handler/Tests/Network/Udp/WorkersTest.hpp new file mode 100644 index 00000000..cb42e6aa --- /dev/null +++ b/src/Handler/Tests/Network/Udp/WorkersTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_WORKERSTEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_WORKERSTEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace udp +{namespace tests +{ + +class WorkersTest: public ::AbstractTest +{ +public: + WorkersTest(); + virtual ~WorkersTest(); + +private: + virtual int vStart(); +}; + +}}}}} // namespace flame_ide::handler::network::udp::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_WORKERSTEST_HPP diff --git a/src/Handler/Tests/Network/UdpTest.cpp b/src/Handler/Tests/Network/UdpTest.cpp new file mode 100644 index 00000000..777782ed --- /dev/null +++ b/src/Handler/Tests/Network/UdpTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +UdpTest::UdpTest() : ::AbstractTest("Udp") +{} + +UdpTest::~UdpTest() = default; + +int UdpTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/UdpTest.hpp b/src/Handler/Tests/Network/UdpTest.hpp new file mode 100644 index 00000000..e013242b --- /dev/null +++ b/src/Handler/Tests/Network/UdpTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class UdpTest: public ::AbstractTest +{ +public: + UdpTest(); + virtual ~UdpTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_UDP_TEST_HPP diff --git a/src/Handler/Tests/Network/WorkerBaseTest.cpp b/src/Handler/Tests/Network/WorkerBaseTest.cpp new file mode 100644 index 00000000..d5fb4a05 --- /dev/null +++ b/src/Handler/Tests/Network/WorkerBaseTest.cpp @@ -0,0 +1,19 @@ +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +WorkerBaseTest::WorkerBaseTest() : ::AbstractTest("WorkerBase") +{} + +WorkerBaseTest::~WorkerBaseTest() = default; + +int WorkerBaseTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/WorkerBaseTest.hpp b/src/Handler/Tests/Network/WorkerBaseTest.hpp new file mode 100644 index 00000000..5694d925 --- /dev/null +++ b/src/Handler/Tests/Network/WorkerBaseTest.hpp @@ -0,0 +1,25 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_WORKER_BASE_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_WORKER_BASE_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class WorkerBaseTest: public ::AbstractTest +{ +public: + WorkerBaseTest(); + virtual ~WorkerBaseTest(); + +private: + virtual int vStart(); +}; + + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_WORKER_BASE_TEST_HPP diff --git a/src/Handler/Tests/Network/WorkersTest.cpp b/src/Handler/Tests/Network/WorkersTest.cpp new file mode 100644 index 00000000..059f02f9 --- /dev/null +++ b/src/Handler/Tests/Network/WorkersTest.cpp @@ -0,0 +1,20 @@ +#include +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +WorkersTest::WorkersTest() : ::AbstractTest("Workers") +{} + +WorkersTest::~WorkersTest() = default; + +int WorkersTest::vStart() +{ + return ResultType::SUCCESS; +} + +}}}} // namespace flame_ide::handler::network::tests diff --git a/src/Handler/Tests/Network/WorkersTest.hpp b/src/Handler/Tests/Network/WorkersTest.hpp new file mode 100644 index 00000000..8837d305 --- /dev/null +++ b/src/Handler/Tests/Network/WorkersTest.hpp @@ -0,0 +1,24 @@ +#ifndef FLAMEIDE_SRC_HANDLER_NETWORK_WORKERS_TEST_HPP +#define FLAMEIDE_SRC_HANDLER_NETWORK_WORKERS_TEST_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace network +{namespace tests +{ + +class WorkersTest: public ::AbstractTest +{ +public: + WorkersTest(); + virtual ~WorkersTest(); + +private: + virtual int vStart(); +}; + +}}}} // namespace flame_ide::handler::network::tests + +#endif // FLAMEIDE_SRC_HANDLER_NETWORK_WORKERS_TEST_HPP diff --git a/src/Handler/Tests/Sources.cmake b/src/Handler/Tests/Sources.cmake new file mode 100644 index 00000000..c7f678a7 --- /dev/null +++ b/src/Handler/Tests/Sources.cmake @@ -0,0 +1,5 @@ +set (SOURCE_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/TestAggregator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestAggregator.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp +) diff --git a/src/Handler/Tests/TestAggregator.cpp b/src/Handler/Tests/TestAggregator.cpp new file mode 100644 index 00000000..3440755c --- /dev/null +++ b/src/Handler/Tests/TestAggregator.cpp @@ -0,0 +1,60 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace flame_ide +{namespace handler +{namespace tests +{ + +TestAggregator::TestAggregator() : ::TestAggregator("Handler") +{ + // UDP + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + + // TCP + pushBackTest(std::make_shared()); + + // Handler + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); + pushBackTest(std::make_shared()); +} + +}}} // namespace flame_ide::handler::tests diff --git a/src/Handler/Tests/TestAggregator.hpp b/src/Handler/Tests/TestAggregator.hpp new file mode 100644 index 00000000..4921a684 --- /dev/null +++ b/src/Handler/Tests/TestAggregator.hpp @@ -0,0 +1,20 @@ +#ifndef FLAMEIDE_SRC_HANDLER_TESTS_TESTAGGREGATOR_HPP +#define FLAMEIDE_SRC_HANDLER_TESTS_TESTAGGREGATOR_HPP + +#include + +namespace flame_ide +{namespace handler +{namespace tests +{ + +class TestAggregator: public ::TestAggregator +{ +public: + TestAggregator(); + virtual ~TestAggregator() = default; +}; + +}}} // namespace flame_ide::handler::tests + +#endif // FLAMEIDE_SRC_HANDLER_TESTS_TESTAGGREGATOR_HPP diff --git a/src/Handler/Tests/main.cpp b/src/Handler/Tests/main.cpp new file mode 100644 index 00000000..9f7d3bd8 --- /dev/null +++ b/src/Handler/Tests/main.cpp @@ -0,0 +1,6 @@ +#include + +int main() +{ + return flame_ide::handler::tests::TestAggregator().start(); +} diff --git a/src/Os/Async/Network/EventCatcherBase.cpp b/src/Os/Async/Network/EventCatcherBase.cpp index 21390952..9d5b76d0 100644 --- a/src/Os/Async/Network/EventCatcherBase.cpp +++ b/src/Os/Async/Network/EventCatcherBase.cpp @@ -11,22 +11,100 @@ SocketQueues &EventCatcherBase::queues() noexcept return socketQueues; } -void EventCatcherBase::setNotificator(const NotificatorBase &inputNotificator) noexcept +void EventCatcherBase::setNotificator(UdpServerNotificatorBase ¬ificator) noexcept { - notificationObject = decltype(notificationObject)(inputNotificator); + notificationObjects.udpServer + = decltype(notificationObjects.udpServer){ notificator }; } -void EventCatcherBase::unsetNotificator() noexcept +void EventCatcherBase::setNotificator(UdpClientNotificatorBase ¬ificator) noexcept { - notificationObject = decltype(notificationObject)(nullptr); + notificationObjects.udpClient + = decltype(notificationObjects.udpClient){ notificator }; } -// protected +void EventCatcherBase::setNotificator(TcpServerNotificatorBase ¬ificator) noexcept +{ + notificationObjects.tcpServer + = decltype(notificationObjects.tcpServer){ notificator }; +} + +void EventCatcherBase::setNotificator( + TcpAcceptedConnectionNotificatorBase ¬ificator +) noexcept +{ + notificationObjects.tcpAcceptedConnection + = decltype(notificationObjects.tcpAcceptedConnection){ notificator }; +} + +void EventCatcherBase::setNotificator(TcpClientNotificatorBase ¬ificator) noexcept +{ + notificationObjects.tcpClient + = decltype(notificationObjects.tcpClient){ notificator }; +} + +void EventCatcherBase::unsetNotificator(tag::UdpServer) noexcept +{ + notificationObjects.udpServer = nullptr; +} + +void EventCatcherBase::unsetNotificator(tag::UdpClient) noexcept +{ + notificationObjects.udpClient = nullptr; +} + +void EventCatcherBase::unsetNotificator(tag::TcpServer) noexcept +{ + notificationObjects.tcpServer = nullptr; +} + +void EventCatcherBase::unsetNotificator(tag::TcpAcceptedConnection) noexcept +{ + notificationObjects.tcpAcceptedConnection = nullptr; +} + +void EventCatcherBase::unsetNotificator(tag::TcpClient) noexcept +{ + notificationObjects.tcpClient = nullptr; +} + +void EventCatcherBase::unsetNotificators() noexcept +{ + unsetNotificator(tag::UdpServer{}); + unsetNotificator(tag::UdpClient{}); + unsetNotificator(tag::TcpServer{}); + unsetNotificator(tag::TcpAcceptedConnection{}); + unsetNotificator(tag::TcpClient{}); +} + +void EventCatcherBase::notify(tag::UdpServer) const noexcept +{ + if (notificationObjects.udpServer) + notificationObjects.udpServer.get()(); +} + +void EventCatcherBase::notify(tag::UdpClient) const noexcept +{ + if (notificationObjects.udpClient) + notificationObjects.udpClient.get()(); +} + +void EventCatcherBase::notify(tag::TcpServer) const noexcept +{ + if (notificationObjects.tcpServer) + notificationObjects.tcpServer.get()(); +} + +void EventCatcherBase::notify(tag::TcpAcceptedConnection) const noexcept +{ + if (notificationObjects.tcpAcceptedConnection) + notificationObjects.tcpAcceptedConnection.get()(); +} -void EventCatcherBase::notify() const noexcept +void EventCatcherBase::notify(tag::TcpClient) const noexcept { - if (notificationObject) - notificationObject.get()(); + if (notificationObjects.tcpClient) + notificationObjects.tcpClient.get()(); } }}}} // namespace flame_ide::os::async::network diff --git a/src/Os/Async/Network/EventCatcherBase.hpp b/src/Os/Async/Network/EventCatcherBase.hpp index 9d210f47..d27d576c 100644 --- a/src/Os/Async/Network/EventCatcherBase.hpp +++ b/src/Os/Async/Network/EventCatcherBase.hpp @@ -19,6 +19,13 @@ namespace flame_ide /// class EventCatcherBase { +public: + using UdpServerTag = tag::UdpServer; + using UdpClientTag = tag::UdpClient; + using TcpServerTag = tag::TcpServer; + using TcpAcceptedConnectionTag = tag::TcpAcceptedConnection; + using TcpClientTag = tag::TcpServer; + public: virtual ~EventCatcherBase() noexcept = default; @@ -47,17 +54,34 @@ class EventCatcherBase /// @param notificator /// @note Implementation of NotificatorBase needs thread and signal safe /// - void setNotificator(const NotificatorBase ¬ificator) noexcept; + void setNotificator(UdpServerNotificatorBase ¬ificator) noexcept; + void setNotificator(UdpClientNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpServerNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpAcceptedConnectionNotificatorBase ¬ificator) noexcept; + void setNotificator(TcpClientNotificatorBase ¬ificator) noexcept; /// /// @brief unsetNotifcator /// - void unsetNotificator() noexcept; + void unsetNotificator(tag::UdpServer) noexcept; + void unsetNotificator(tag::UdpClient) noexcept; + void unsetNotificator(tag::TcpServer) noexcept; + void unsetNotificator(tag::TcpAcceptedConnection) noexcept; + void unsetNotificator(tag::TcpClient) noexcept; + + /// + /// @brief unsetNotifcators + /// + void unsetNotificators() noexcept; /// /// @brief notify /// - void notify() const noexcept; + void notify(tag::UdpServer) const noexcept; + void notify(tag::UdpClient) const noexcept; + void notify(tag::TcpServer) const noexcept; + void notify(tag::TcpAcceptedConnection) const noexcept; + void notify(tag::TcpClient) const noexcept; public: static EventCatcherBase &get() noexcept; // platform impl @@ -67,7 +91,15 @@ class EventCatcherBase private: SocketQueues socketQueues; - ConstReferenceWrapper notificationObject = nullptr; + struct + { + ReferenceWrapper udpServer = nullptr; + ReferenceWrapper udpClient = nullptr; + ReferenceWrapper tcpServer = nullptr; + ReferenceWrapper + tcpAcceptedConnection = nullptr; + ReferenceWrapper tcpClient = nullptr; + } notificationObjects; }; }}}} // namespace flame_ide::os::async::network diff --git a/src/Os/Async/Network/QueuedArray.hpp b/src/Os/Async/Network/QueuedArray.hpp index 2b5b8986..89a5d813 100644 --- a/src/Os/Async/Network/QueuedArray.hpp +++ b/src/Os/Async/Network/QueuedArray.hpp @@ -23,6 +23,8 @@ class QueuedArray bool push(Type value) noexcept; templates::Expected pop(Type initValue = {}) noexcept; + Types::size_t getSize() const noexcept; + private: using Array = templates::StaticArray; using Pointer = templates::UniquePointer; @@ -104,6 +106,13 @@ QueuedArray::pop(Type initValue) noexcept return templates::Expected{ value }; } +template +Types::size_t QueuedArray::getSize() const noexcept +{ + os::threads::Locker locker{ spin }; + return count; +} + }}}} // namespace flame_ide::os::async::network #endif // ASYNC_NETWORK_QUEUEDARRAY_HPP diff --git a/src/Os/Async/Network/Registrar.cpp b/src/Os/Async/Network/Registrar.cpp index a1df1410..726210d9 100644 --- a/src/Os/Async/Network/Registrar.cpp +++ b/src/Os/Async/Network/Registrar.cpp @@ -7,6 +7,38 @@ #include #include +#include + +namespace flame_ide +{namespace os +{namespace async +{namespace network +{ +namespace anonymous { namespace { + +static constexpr auto ASYNC_EVENT_INIT_VALUE = AsyncEvent{}; + +}} // namespace anonymous +}}}} // namespace flame_ide::os::async::network + +namespace flame_ide +{namespace os +{namespace async +{namespace network +{ + +bool operator==(const AsyncEvent &ae1, const AsyncEvent &ae2) noexcept +{ + return ((ae1.descriptor == ae2.descriptor) && (ae1.event == ae2.event)); +} + +bool operator!=(const AsyncEvent &ae1, const AsyncEvent &ae2) noexcept +{ + return !(ae1 == ae2); +} + +}}}} // namespace flame_ide::os::async::network + namespace flame_ide {namespace os {namespace async @@ -17,13 +49,30 @@ Registrar::Registrar() noexcept = default; Registrar::~Registrar() noexcept = default; +SocketsInfo Registrar::getInfo() const noexcept +{ + static constexpr SocketsInfo::Info MAX_INFO = SocketsInfo::Info { + generated::network::Config::UDP_SERVERS + , generated::network::Config::UDP_CLIENTS + , generated::network::Config::TCP_SERVERS + , generated::network::Config::TCP_CLIENTS + }; + + auto &queues = EventCatcherBase::get().queues(); + SocketsInfo config = { MAX_INFO, SocketsInfo::Info { + queues.udpServers().getSize(), queues.udpClients().getSize() + , queues.tcpServers().getSize(), queues.tcpClients().getSize() + } }; + return config; +} + // Registrar::add os::Status Registrar::add(const os::network::UdpServer &socket) noexcept { auto &queue = EventCatcherBase::get().queues().udpServers(); if (!queue) - queue.init(os::SOCKET_INVALID.descriptor); + queue.init(anonymous::ASYNC_EVENT_INIT_VALUE); return EventCatcherBase::get().enable(socket.native().descriptor); } @@ -31,7 +80,7 @@ os::Status Registrar::add(const os::network::UdpClient &socket) noexcept { auto &queue = EventCatcherBase::get().queues().udpClients(); if (!queue) - queue.init(os::SOCKET_INVALID.descriptor); + queue.init(anonymous::ASYNC_EVENT_INIT_VALUE); return EventCatcherBase::get().enable(socket.native().descriptor); } @@ -47,7 +96,7 @@ os::Status Registrar::add(const os::network::TcpServer::WithClient &socket) noex { auto &queue = EventCatcherBase::get().queues().tcpServers(); if (!queue) - queue.init(os::SOCKET_INVALID.descriptor); + queue.init(anonymous::ASYNC_EVENT_INIT_VALUE); return EventCatcherBase::get().enable(socket.native().descriptor); } @@ -55,7 +104,7 @@ os::Status Registrar::add(const os::network::TcpClient &socket) noexcept { auto &queue = EventCatcherBase::get().queues().tcpClients(); if (!queue) - queue.init(os::SOCKET_INVALID.descriptor); + queue.init(anonymous::ASYNC_EVENT_INIT_VALUE); return EventCatcherBase::get().enable(socket.native().descriptor); } @@ -88,10 +137,10 @@ os::Status Registrar::remove(const os::network::TcpClient &socket) noexcept // Registrar::pop* -os::SocketDescriptor Registrar::popUdpServer() noexcept +AsyncEvent Registrar::popUdpServer() noexcept { - os::SocketDescriptor descriptor = os::SOCKET_INVALID.descriptor; - EventCatcherBase::get().queues().udpServers().pop(os::SOCKET_INVALID.descriptor) + AsyncEvent descriptor = anonymous::ASYNC_EVENT_INIT_VALUE; + EventCatcherBase::get().queues().udpServers().pop(anonymous::ASYNC_EVENT_INIT_VALUE) .ifResult([&descriptor](auto &&actualDescriptor) { descriptor = actualDescriptor; @@ -100,10 +149,10 @@ os::SocketDescriptor Registrar::popUdpServer() noexcept return descriptor; } -os::SocketDescriptor Registrar::popUdpClient() noexcept +AsyncEvent Registrar::popUdpClient() noexcept { - os::SocketDescriptor descriptor = os::SOCKET_INVALID.descriptor; - EventCatcherBase::get().queues().udpClients().pop(os::SOCKET_INVALID.descriptor) + AsyncEvent descriptor = anonymous::ASYNC_EVENT_INIT_VALUE; + EventCatcherBase::get().queues().udpClients().pop(anonymous::ASYNC_EVENT_INIT_VALUE) .ifResult([&descriptor](auto &&actualDescriptor) { descriptor = actualDescriptor; @@ -124,10 +173,10 @@ AcceptedConnection Registrar::popTcpServerAcception() noexcept return connection; } -os::SocketDescriptor Registrar::popTcpServer() noexcept +AsyncEvent Registrar::popTcpServer() noexcept { - os::SocketDescriptor descriptor = os::SOCKET_INVALID.descriptor; - EventCatcherBase::get().queues().tcpServers().pop(os::SOCKET_INVALID.descriptor) + AsyncEvent descriptor = anonymous::ASYNC_EVENT_INIT_VALUE; + EventCatcherBase::get().queues().tcpServers().pop(anonymous::ASYNC_EVENT_INIT_VALUE) .ifResult([&descriptor](auto &&actualDescriptor) { descriptor = actualDescriptor; @@ -136,10 +185,10 @@ os::SocketDescriptor Registrar::popTcpServer() noexcept return descriptor; } -os::SocketDescriptor Registrar::popTcpClient() noexcept +AsyncEvent Registrar::popTcpClient() noexcept { - os::SocketDescriptor descriptor = os::SOCKET_INVALID.descriptor; - EventCatcherBase::get().queues().tcpClients().pop(os::SOCKET_INVALID.descriptor) + AsyncEvent descriptor = anonymous::ASYNC_EVENT_INIT_VALUE; + EventCatcherBase::get().queues().tcpClients().pop(anonymous::ASYNC_EVENT_INIT_VALUE) .ifResult([&descriptor](auto &&actualDescriptor) { descriptor = actualDescriptor; @@ -148,54 +197,43 @@ os::SocketDescriptor Registrar::popTcpClient() noexcept return descriptor; } -// Registrar::push* - -bool Registrar::pushUdpServer(os::SocketDescriptor socket) noexcept -{ - return EventCatcherBase::get().queues().udpServers().push(socket); -} +// notificator -bool Registrar::pushUdpClient(os::SocketDescriptor socket) noexcept +void Registrar::setNotificator(UdpServerNotificatorBase ¬ificator) noexcept { - return EventCatcherBase::get().queues().udpClients().push(socket); + EventCatcherBase::get().setNotificator(notificator); } - -bool Registrar::pushTcpServerAcception(AcceptedConnection connection) noexcept +void Registrar::setNotificator(UdpClientNotificatorBase ¬ificator) noexcept { - return EventCatcherBase::get().queues().tcpAcceptedConnections().push(connection); + EventCatcherBase::get().setNotificator(notificator); } - -bool Registrar::pushTcpServer(os::SocketDescriptor socket) noexcept +void Registrar::setNotificator(TcpServerNotificatorBase ¬ificator) noexcept { - return EventCatcherBase::get().queues().tcpServers().push(socket); + EventCatcherBase::get().setNotificator(notificator); } - -bool Registrar::pushTcpClient(os::SocketDescriptor socket) noexcept +void Registrar::setNotificator(TcpAcceptedConnectionNotificatorBase ¬ificator) noexcept { - return EventCatcherBase::get().queues().tcpClients().push(socket); + EventCatcherBase::get().setNotificator(notificator); } - -// notificator - -void Registrar::setNotificator(const NotificatorBase ¬ificator) noexcept +void Registrar::setNotificator(TcpClientNotificatorBase ¬ificator) noexcept { EventCatcherBase::get().setNotificator(notificator); } -void Registrar::unsetNotificator() noexcept +void Registrar::unsetNotificators() noexcept { - EventCatcherBase::get().unsetNotificator(); + EventCatcherBase::get().unsetNotificators(); } // other void Registrar::clear() noexcept { - while (popUdpServer() != os::SOCKET_INVALID.descriptor); - while (popUdpClient() != os::SOCKET_INVALID.descriptor); + while (popUdpServer() != anonymous::ASYNC_EVENT_INIT_VALUE); + while (popUdpClient() != anonymous::ASYNC_EVENT_INIT_VALUE); while (popTcpServerAcception()); - while (popTcpServer() != os::SOCKET_INVALID.descriptor); - while (popTcpClient() != os::SOCKET_INVALID.descriptor); + while (popTcpServer() != anonymous::ASYNC_EVENT_INIT_VALUE); + while (popTcpClient() != anonymous::ASYNC_EVENT_INIT_VALUE); } }}}} // namespace flame_ide::os::async::network diff --git a/src/Os/Async/Network/Types.hpp b/src/Os/Async/Network/Types.hpp index 206ae6a8..2de356ae 100644 --- a/src/Os/Async/Network/Types.hpp +++ b/src/Os/Async/Network/Types.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -17,16 +18,16 @@ namespace flame_ide static constexpr Types::size_t FACTOR = 4; template -using Descriptors = templates::StaticArray; +using Events = templates::StaticArray; -using UdpServers = Descriptors; -using UdpClients = Descriptors; -using TcpServers = Descriptors< +using UdpServers = Events; +using UdpClients = Events; +using TcpServers = Events< generated::network::Config::TCP_SERVERS * generated::network::Config::TCP_SERVER_BACKLOG * FACTOR >; -using TcpClients = Descriptors; +using TcpClients = Events; using AcceptedConnections = templates::StaticArray< AcceptedConnection, generated::network::Config::TCP_SERVER_BACKLOG * FACTOR diff --git a/src/Os/Network/UdpServer.cpp b/src/Os/Network/UdpServer.cpp index 76f38d44..d86e46c7 100644 --- a/src/Os/Network/UdpServer.cpp +++ b/src/Os/Network/UdpServer.cpp @@ -19,8 +19,7 @@ UdpServer::UdpServer(Ipv4::Port port) noexcept : NetworkBase(socket::createUdpSe UdpServer &UdpServer::operator=(UdpServer &&server) noexcept { - NetworkBase &&base = static_cast(server); - operator=(move(base)); + operator=(move(static_cast(server))); return *this; } diff --git a/src/Os/Posix/Async/Network/EventCatcher.cpp b/src/Os/Posix/Async/Network/EventCatcher.cpp index ea1dc14b..cb8023e0 100644 --- a/src/Os/Posix/Async/Network/EventCatcher.cpp +++ b/src/Os/Posix/Async/Network/EventCatcher.cpp @@ -1,9 +1,12 @@ #include +#include +#include #include #include #include +#include namespace flame_ide {namespace os @@ -15,6 +18,45 @@ namespace anonymous{namespace{ static constexpr decltype(SIGPOLL) SIGNAL_POLLING = os::posix::Signal::POLL; +using BandEvent = decltype(siginfo_t{}.si_band); + +enum PollingFlags: BandEvent +{ + INPUT = POLLIN + , PRIORITY = POLLPRI + , OUTPUT = POLLOUT + , ERROR = POLLERR + , HANG_UP = POLLHUP + , INVALID_REQUEST = POLLNVAL + , READ_NORMAL = POLLRDNORM + , READ_PRIORITY = POLLRDBAND + , WRITE_NORMAL = POLLWRNORM + , WRITE_PRIORITY = POLLWRBAND +}; + +::flame_ide::os::async::network::EventType +convertBandEventsToAsyncEvent(BandEvent events) +{ + using ::flame_ide::os::async::network::EventType; + + if ((events & PollingFlags::ERROR) || (events & PollingFlags::INVALID_REQUEST)) + return EventType::INVALID; + + auto eventType = EventType::INIT; + + if ((events & PollingFlags::INPUT) || (events & PollingFlags::READ_NORMAL)) + eventType = EventType::READ; + + if ((events & PollingFlags::OUTPUT) || (events & PollingFlags::WRITE_NORMAL)) + { + eventType = (eventType == EventType::READ) + ? EventType::READ_WRITE + : EventType::WRITE; + } + + return eventType; +} + }} // namespace anonymous }}}}} // namespace flame_ide::os::posix::async::network @@ -88,7 +130,9 @@ EventCatcher::SigAction EventCatcher::makeSigAction() noexcept return action; } -void EventCatcher::signalHandler(int signal, const siginfo_t *info, ucontext_t *) noexcept +void EventCatcher::signalHandler( + int signal, const siginfo_t *info, ucontext_t * +) noexcept { using os::network::NetworkBase; @@ -96,25 +140,45 @@ void EventCatcher::signalHandler(int signal, const siginfo_t *info, ucontext_t * return; const auto descriptor = info->si_fd; + + /* + POLLIN = (bin) 1 // 0x001 // There is data to read + POLLPRI = (bin) 10 // 0x002 // There is urgent data to read + POLLOUT = (bin) 100 // 0x004 // Writing now will not block + POLLERR = (bin) 1000 // 0x008 // Error condition + POLLHUP = (bin) 10000 // 0x010 // Hung up + POLLNVAL = (bin) 100000 // 0x020 // Invalid polling request + + // defined __USE_XOPEN || defined __USE_XOPEN2K8 + POLLRDNORM = (bin) 1000000 // 0x040 // Normal data may be read + POLLRDBAND = (bin) 10000000 // 0x080 // Priority data may be read + POLLWRNORM = (bin) 100000000 // 0x100 // Writing now will not block + POLLWRBAND = (bin) 1000000000 // 0x200 // Priority data may be written + + // __USE_GNU + POLLMSG = (bin) 10000000000 // 0x400 + POLLREMOVE = (bin) 1000000000000 // 0x1000 + POLLRDHUP = (bin) 10000000000000 // 0x2000 + */ + const auto events = info->si_band; + switch (NetworkBase::callbacks().type(Socket{ {}, descriptor })) { case NetworkBase::SocketType::STREAM: - handleTcp(descriptor); + handleTcp(descriptor, events); break; case NetworkBase::SocketType::DATAGRAM: - handleUdp(descriptor); + handleUdp(descriptor, events); break; case NetworkBase::SocketType::UNKNOWN: default: return; } - - EventCatcher::get().notify(); } -void EventCatcher::handleTcp(SocketDescriptor descriptor) noexcept +void EventCatcher::handleTcp(SocketDescriptor descriptor, SigEvents events) noexcept { using os::network::TcpServer; @@ -123,13 +187,25 @@ void EventCatcher::handleTcp(SocketDescriptor descriptor) noexcept if (!serverControl().isServer(socket)) { // Signal has been received from client's socket - EventCatcher::get().queues().tcpClients().push(descriptor); + EventCatcher::get().queues().tcpClients().push( + flame_ide::os::async::network::AsyncEvent { + descriptor + , anonymous::convertBandEventsToAsyncEvent(events) + } + ); + EventCatcher::get().notify(EventCatcher::TcpClientTag{}); return; } if (!serverControl().isListener(socket)) { // Signal has been received from accepted server's socket - EventCatcher::get().queues().tcpServers().push(descriptor); + EventCatcher::get().queues().tcpServers().push( + flame_ide::os::async::network::AsyncEvent { + descriptor + , anonymous::convertBandEventsToAsyncEvent(events) + } + ); + EventCatcher::get().notify(EventCatcher::TcpServerTag{}); return; } @@ -140,15 +216,33 @@ void EventCatcher::handleTcp(SocketDescriptor descriptor) noexcept return; EventCatcher::get().queues().tcpAcceptedConnections() .push({ socket.descriptor, client }); + EventCatcher::get().notify(EventCatcher::TcpAcceptedConnectionTag{}); return; } -void EventCatcher::handleUdp(SocketDescriptor descriptor) noexcept +void EventCatcher::handleUdp(SocketDescriptor descriptor, SigEvents events) noexcept { using os::network::NetworkBase; - (NetworkBase::callbacks().isServer(Socket{ {}, descriptor })) - ? EventCatcher::get().queues().udpServers().push(descriptor) - : EventCatcher::get().queues().udpClients().push(descriptor); + if(NetworkBase::callbacks().isServer(Socket{ {}, descriptor })) + { + EventCatcher::get().queues().udpServers().push( + flame_ide::os::async::network::AsyncEvent { + descriptor + , anonymous::convertBandEventsToAsyncEvent(events) + } + ); + EventCatcher::get().notify(EventCatcher::UdpServerTag{}); + } + else + { + EventCatcher::get().queues().udpClients().push( + flame_ide::os::async::network::AsyncEvent { + descriptor + , anonymous::convertBandEventsToAsyncEvent(events) + } + ); + EventCatcher::get().notify(EventCatcher::UdpClientTag{}); + } } os::Status EventCatcher::enableSignal(SocketDescriptor descriptor) noexcept diff --git a/src/Os/Posix/Async/Network/EventCatcher.hpp b/src/Os/Posix/Async/Network/EventCatcher.hpp index 26f1d967..0c3fa2a2 100644 --- a/src/Os/Posix/Async/Network/EventCatcher.hpp +++ b/src/Os/Posix/Async/Network/EventCatcher.hpp @@ -25,11 +25,12 @@ class EventCatcher: public os::async::network::EventCatcherBase private: using SigAction = struct ::sigaction; using SigActionHandler = decltype(SigAction{}.sa_sigaction); + using SigEvents = decltype(siginfo_t{}.si_band); static SigAction makeSigAction() noexcept; static void signalHandler(int signal, const siginfo_t *info, ucontext_t *) noexcept; - static void handleTcp(SocketDescriptor descriptor) noexcept; - static void handleUdp(SocketDescriptor descriptor) noexcept; + static void handleTcp(SocketDescriptor descriptor, SigEvents events) noexcept; + static void handleUdp(SocketDescriptor descriptor, SigEvents events) noexcept; static os::Status enableSignal(SocketDescriptor descriptor) noexcept; static os::Status disableSignal(SocketDescriptor descriptor) noexcept; diff --git a/src/Os/Tests/Async/Network/RegistrarTest.cpp b/src/Os/Tests/Async/Network/RegistrarTest.cpp index 2997c727..fb502c22 100644 --- a/src/Os/Tests/Async/Network/RegistrarTest.cpp +++ b/src/Os/Tests/Async/Network/RegistrarTest.cpp @@ -25,7 +25,8 @@ namespace anonymous {namespace { -class NotificatorTest: public NotificatorBase +template +class NotificatorTest: public NotificatorBaseType { public: bool isNotified() const @@ -34,7 +35,7 @@ class NotificatorTest: public NotificatorBase return notification; } private: - virtual void operator()() const noexcept override + virtual void operator()() noexcept override { os::threads::Locker{ mutex }; notification = true; @@ -102,7 +103,7 @@ int RegistrarTest::vStart() "UdpServer notify" , [this] { - return udpNotify(); + return udpServerNotify(); } )); return RegistrarTest::SUCCESS; @@ -126,16 +127,16 @@ int RegistrarTest::udpServer() } // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; + AsyncEvent resultEvent{}; for (auto i = numberOfTries - ; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor + ; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor ; --i ) { - resultDescriptor = registar.popUdpServer(); + resultEvent = registar.popUdpServer(); } - IN_CASE_CHECK(resultDescriptor != os::SOCKET_INVALID.descriptor); - IN_CASE_CHECK(resultDescriptor == server.native().descriptor); + IN_CASE_CHECK(resultEvent.descriptor != os::SOCKET_INVALID.descriptor); + IN_CASE_CHECK(resultEvent.descriptor == server.native().descriptor); auto fromServer = server.wait(); IN_CASE_CHECK(fromServer.getStatus() == sizeof(MESSAGE_PING)); @@ -177,10 +178,10 @@ int RegistrarTest::udpClient() IN_CASE_CHECK(result == sizeof(MESSAGE_PING)); // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; - for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor; --i) + AsyncEvent resultEvent{}; + for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor; --i) { - resultDescriptor = registar.popUdpServer(); + resultEvent = registar.popUdpServer(); } } @@ -217,12 +218,12 @@ int RegistrarTest::udpClient() ); // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; - for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor; --i) + AsyncEvent resultEvent{}; + for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor; --i) { - resultDescriptor = registar.popUdpClient(); + resultEvent = registar.popUdpClient(); } - IN_CASE_CHECK(resultDescriptor == client.native().descriptor); + IN_CASE_CHECK(resultEvent.descriptor == client.native().descriptor); } IN_CASE_CHECK(registar.remove(client) == os::STATUS_SUCCESS); } @@ -298,13 +299,13 @@ int RegistrarTest::tcpServer() IN_CASE_CHECK(client.disconnect() == os::STATUS_SUCCESS); // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; - for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor; --i) + AsyncEvent resultEvent{}; + for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor; --i) { - resultDescriptor = registar.popTcpServer(); + resultEvent = registar.popTcpServer(); } - IN_CASE_CHECK(resultDescriptor != os::SOCKET_INVALID.descriptor); - IN_CASE_CHECK(resultDescriptor == serverConnection.native().descriptor); + IN_CASE_CHECK(resultEvent.descriptor != os::SOCKET_INVALID.descriptor); + IN_CASE_CHECK(resultEvent.descriptor == serverConnection.native().descriptor); IN_CASE_CHECK(registar.remove(serverConnection) == os::STATUS_SUCCESS); @@ -348,23 +349,23 @@ int RegistrarTest::tcpClient() ); // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; - for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor; --i) + AsyncEvent resultEvent{}; + for (auto i = numberOfTries; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor; --i) { - resultDescriptor = registar.popTcpClient(); + resultEvent = registar.popTcpClient(); } - IN_CASE_CHECK(resultDescriptor != os::SOCKET_INVALID.descriptor); - IN_CASE_CHECK(resultDescriptor == client.native().descriptor); + IN_CASE_CHECK(resultEvent.descriptor != os::SOCKET_INVALID.descriptor); + IN_CASE_CHECK(resultEvent.descriptor == client.native().descriptor); return RegistrarTest::SUCCESS; } -int RegistrarTest::udpNotify() +int RegistrarTest::udpServerNotify() { os::network::UdpServer server{ port }; os::network::UdpClient client{ ipv4 }; - anonymous::NotificatorTest notificator; + anonymous::NotificatorTest notificator; Registrar registar; registar.setNotificator(notificator); @@ -381,16 +382,18 @@ int RegistrarTest::udpNotify() } // Wait - os::SocketDescriptor resultDescriptor = os::SOCKET_INVALID.descriptor; + AsyncEvent resultEvent{}; for (auto i = numberOfTries - ; i != 0 && os::SOCKET_INVALID.descriptor == resultDescriptor + ; i != 0 && os::SOCKET_INVALID.descriptor == resultEvent.descriptor ; --i ) { - resultDescriptor = registar.popUdpServer(); + resultEvent = registar.popUdpServer(); } - IN_CASE_CHECK(resultDescriptor != os::SOCKET_INVALID.descriptor); - IN_CASE_CHECK(resultDescriptor == server.native().descriptor); + + IN_CASE_CHECK(notificator.isNotified() == true); + IN_CASE_CHECK(resultEvent.descriptor != os::SOCKET_INVALID.descriptor); + IN_CASE_CHECK(resultEvent.descriptor == server.native().descriptor); auto fromServer = server.wait(); IN_CASE_CHECK(fromServer.getStatus() == sizeof(MESSAGE_PING)); @@ -409,12 +412,10 @@ int RegistrarTest::udpNotify() [®istar]() { registar.clear(); - registar.unsetNotificator(); + registar.unsetNotificators(); } ); - IN_CASE_CHECK(notificator.isNotified() == true); - return RegistrarTest::SUCCESS; } diff --git a/src/Os/Tests/Async/Network/RegistrarTest.hpp b/src/Os/Tests/Async/Network/RegistrarTest.hpp index 4c33b1fd..6fb27c8c 100644 --- a/src/Os/Tests/Async/Network/RegistrarTest.hpp +++ b/src/Os/Tests/Async/Network/RegistrarTest.hpp @@ -26,7 +26,7 @@ struct RegistrarTest: public ::AbstractTest int tcpServer(); int tcpClient(); - int udpNotify(); + int udpServerNotify(); private: const Types::size_t numberOfTries = NumberLimitValueMax; diff --git a/src/Os/Threads/ConditionVarable.cpp b/src/Os/Threads/ConditionVarable.cpp index d9c0f2a9..c63226e4 100644 --- a/src/Os/Threads/ConditionVarable.cpp +++ b/src/Os/Threads/ConditionVarable.cpp @@ -23,19 +23,6 @@ void ConditionVariable::wait() noexcept --counter; } -bool ConditionVariable::tryWait() noexcept -{ - bool lockStatus = locker.tryLock(); - if (lockStatus) - locker.unlock(); - return lockStatus; -} - -void ConditionVariable::unwait() noexcept -{ - --counter; -} - bool ConditionVariable::isWait() const noexcept { return counter.current(); @@ -43,7 +30,7 @@ bool ConditionVariable::isWait() const noexcept void ConditionVariable::notify() noexcept { - volatile auto counterValue = counter.current(); + const volatile auto counterValue = counter.current(); if (!counterValue) return; diff --git a/src/Os/Windows/Async/Network/MessageDispatchThread.cpp b/src/Os/Windows/Async/Network/MessageDispatchThread.cpp index a9e6e240..ad0fc9a5 100644 --- a/src/Os/Windows/Async/Network/MessageDispatchThread.cpp +++ b/src/Os/Windows/Async/Network/MessageDispatchThread.cpp @@ -15,6 +15,24 @@ namespace flame_ide constexpr char WINDOW_CLASS_NAME[] = "AsyncSelect"; +flame_ide::os::async::network::EventType convertFromWinEventToAsyncEvent(Event event) +{ + using AsyncEventType = flame_ide::os::async::network::EventType; + switch (event) { + case Event::READ: + return AsyncEventType::READ; + case Event::WRITE: + return AsyncEventType::WRITE; + case Event::CLOSE: + return AsyncEventType::CLOSE; + + case Event::UNKNOWN: + case Event::CONNECT: + default: + return AsyncEventType::INIT; + } +} + }} // namespace anonymous }}}}} // namespace flame_ide::os::windows::async::network @@ -183,7 +201,6 @@ os::windows::OsResult MessageDispatchThread::action( default: break; } - os::async::network::EventCatcherBase::get().notify(); return ::DefWindowProcA( window, static_cast(message), descriptor, param @@ -202,9 +219,25 @@ void MessageDispatchThread::handleUdp( case Event::WRITE: { if (os::network::NetworkBase::callbacks().isServer(Socket{ descriptor })) - queues.udpServers().push(descriptor); + { + queues.udpServers().push(os::async::network::AsyncEvent{ + descriptor + , anonymous::convertFromWinEventToAsyncEvent(eventValue) + }); + os::async::network::EventCatcherBase::get().notify( + os::async::network::EventCatcherBase::UdpServerTag{} + ); + } else - queues.udpClients().push(descriptor); + { + queues.udpClients().push(os::async::network::AsyncEvent{ + descriptor + , anonymous::convertFromWinEventToAsyncEvent(eventValue) + }); + os::async::network::EventCatcherBase::get().notify( + os::async::network::EventCatcherBase::UdpClientTag{} + ); + } return; } default: @@ -229,16 +262,37 @@ void MessageDispatchThread::handleTcp( Socket{ descriptor }, &status ); if (os::STATUS_SUCCESS == status) + { queues.tcpAcceptedConnections().push({ descriptor, client }); + os::async::network::EventCatcherBase::get().notify( + os::async::network::EventCatcherBase::TcpAcceptedConnectionTag{} + ); + } return; } case Event::READ: case Event::WRITE: { if (os::network::NetworkBase::callbacks().isServer(Socket{ descriptor })) - queues.tcpServers().push(descriptor); + { + queues.tcpServers().push(os::async::network::AsyncEvent{ + descriptor + , anonymous::convertFromWinEventToAsyncEvent(eventValue) + }); + os::async::network::EventCatcherBase::get().notify( + os::async::network::EventCatcherBase::TcpServerTag{} + ); + } else - queues.tcpClients().push(descriptor); + { + queues.tcpClients().push(os::async::network::AsyncEvent{ + descriptor + , anonymous::convertFromWinEventToAsyncEvent(eventValue) + }); + os::async::network::EventCatcherBase::get().notify( + os::async::network::EventCatcherBase::TcpClientTag{} + ); + } return; } default: diff --git a/src/Templates/Tests/HybridVectorTest.cpp b/src/Templates/Tests/HybridVectorTest.cpp index 9a187073..7a9cddde 100644 --- a/src/Templates/Tests/HybridVectorTest.cpp +++ b/src/Templates/Tests/HybridVectorTest.cpp @@ -3,6 +3,8 @@ #include #include +#include "TestClass.hpp" + namespace flame_ide {namespace templates {namespace test diff --git a/src/Templates/Tests/HybridVectorTest.hpp b/src/Templates/Tests/HybridVectorTest.hpp index a9517875..62bb3892 100644 --- a/src/Templates/Tests/HybridVectorTest.hpp +++ b/src/Templates/Tests/HybridVectorTest.hpp @@ -3,7 +3,6 @@ #include #include -#include "TestClass.hpp" #include #include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 080a255e..b2e06ca9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,7 @@ set(TEST_MODULES ${FLAME_SOURCE_SUBMODLUES_PATH}/Common/Tests ${FLAME_SOURCE_SUBMODLUES_PATH}/Os/Tests ${FLAME_SOURCE_SUBMODLUES_PATH}/Crypto/Pkcs11/Tests + ${FLAME_SOURCE_SUBMODLUES_PATH}/Handler/Tests ) foreach(module ${TEST_MODULES})