diff --git a/net/adc_netserver.h b/net/adc_netserver.h new file mode 100644 index 0000000..f03ffd1 --- /dev/null +++ b/net/adc_netserver.h @@ -0,0 +1,169 @@ +#pragma once + +/* + +ABSTRACT DEVICE COMPONENTS LIBRARY + +*/ + +#include +#if __has_include() // POSIX +#define FORK_EXISTS 1 +#include +#include +#include +#endif + +#include + + +namespace adc +{ + + +/* Server session and its abstract decorator */ + +template +class AdcNetServerSession : std::enable_shared_from_this> +{ +public: + using shared_ptr_t = std::shared_ptr; + using weak_ptr_t = std::weak_ptr; + + template + AdcNetServerSession(ImplCtorArgTs&&... ctor_args) : _implUptr(std::forward(ctor_args)...) + { + } + + + virtual ~AdcNetServerSession() = default; + + + auto sessionIdent() const + { + // + return _implUptr->_sessionIdent(); + } + + + virtual void start() + { + // + _implUptr->start(); + } + + virtual void stop() + { + // + _implUptr->stop(); + } + +protected: + std::unique_ptr _implUptr; +}; + + +template > SessionT> +class AdcNetServerSessionDecorator : public SessionT +{ +public: + using SessionT::sessionIdent; + + template + AdcNetServerSessionDecorator(ImplCtorArgTs&&... ctor_args) : SessionT(std::forward(ctor_args)...) + { + } + + virtual ~AdcNetServerSessionDecorator() = default; + + virtual std::invoke_result_t sessionIdent() const = 0; + + virtual void start() = 0; + + virtual void stop() = 0; +}; + + + +/* Server */ + +template +class AdcNetServer +{ +protected: + std::unique_ptr _implUptr; + +public: + template + AdcNetServer(ImplCtorArgTs&&... ctor_args) : _implUptr(std::make_unique(ctor_args)...) + { + } + + + virtual ~AdcNetServer() = default; + + + virtual void start() = 0; + + virtual void stop() = 0; + + template + void start() {}; + + template + void stop() {}; + + // run server as daemon (still only on POSIX OSes) + void daemonize() + { + daemonizePrepare(); + +#ifdef FORK_EXISTS + // get TEMP directory in OS + + auto tmp_path = std::filesystem::temp_directory_path(); + if (tmp_path.empty()) { + tmp_path = std::filesystem::current_path().root_path(); + } + + // _ioContext.notify_fork(asio::execution_context::fork_prepare); + + if (pid_t pid = fork()) { + if (pid > 0) { + exit(0); + } else { + throw std::system_error(errno, std::generic_category(), "CANNOT FORK 1-STAGE"); + } + } + + if (setsid() == -1) { + throw std::system_error(errno, std::generic_category(), "CANNOT FORK SETSID"); + } + + std::filesystem::current_path(tmp_path); + + umask(0); + + if (pid_t pid = fork()) { + if (pid > 0) { + exit(0); + } else { + throw std::system_error(errno, std::generic_category(), "CANNOT FORK 2-STAGE"); + } + } + + close(0); + close(1); + close(2); + + // _ioContext.notify_fork(asio::io_context::fork_child); +#endif + daemonizeFinalize(); + } + + virtual void daemonizePrepare() = 0; + + virtual void daemonizeFinalize() = 0; +}; + +} // namespace adc diff --git a/net/adc_netservice.h b/net/adc_netservice.h index fe64d20..4bcaaa9 100644 --- a/net/adc_netservice.h +++ b/net/adc_netservice.h @@ -7,49 +7,64 @@ ABSTRACT DEVICE COMPONENTS LIBRARY */ +#include +#include #include + namespace adc { -template -class AdcNetServiceInterface : public IOImplT +template +class AdcNetServiceAbstractImplementation; + + +template +class AdcNetService { protected: - AdcNetServiceInterface::socket _socket; - - template - AdcNetServiceInterface(AdcNetServiceInterface::socket&& sock, IOImplCtorArgTs&&... args) - : IOImplT(std::forward(args)...), _socket(sock) - { - } + std::unique_ptr _implUptr; public: - using typename IOImplT::endpoint; - using typename IOImplT::socket; + using typename ImplT::endpoint_t; - virtual ~AdcNetServiceInterface() = default; + using timeout_clock_t = std::chrono::steady_clock; + using timeout_drtn_t = timeout_clock_t::duration; + + static constexpr timeout_drtn_t defaultConnectTimeout = std::chrono::seconds(5); + static constexpr timeout_drtn_t defaultSendTimeout = std::chrono::seconds(5); + static constexpr timeout_drtn_t defaultRecvTimeout = std::chrono::seconds(5); + + AdcNetService(ImplT* impl) : _implUptr(impl) {} + + AdcNetService(std::unique_ptr impl) : _implUptr(std::move(impl)) {} + + virtual ~AdcNetService() = default; /* asynchronuos operations */ // open connection template - auto asyncConnect(AdcNetServiceInterface::endpoint&& end_point, ArgTs&&... args) + auto asyncConnect(const endpoint_t& end_point, + const timeout_drtn_t& timeout = defaultConnectTimeout, + ArgTs&&... args) { - return IOImplT::asyncConnect(end_point); + return _implUptr->asyncConnect(end_point, timeout, std::forward(args)...); } template - auto asyncSend(const NetMessageT& msg, ArgTs&&... args) + auto asyncSend(const NetMessageT& msg, const timeout_drtn_t& timeout = defaultSendTimeout, ArgTs&&... args) { + return _implUptr->asyncSend(msg, timeout, std::forward(args)...); } template - auto asyncReceive(ArgTs&&... args) + auto asyncReceive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args) { + return _implUptr->asyncReceive(timeout, std::forward(args)...); } @@ -57,25 +72,30 @@ public: /* blocking operations */ template - auto connect(const AdcNetServiceInterface::endpoint& end_point, ArgTs&&... args) + auto connect(const endpoint_t& endpoint, const timeout_drtn_t& timeout = defaultConnectTimeout, ArgTs&&... args) { + return _implUptr->connect(endpoint, timeout, std::forward(args)...); } template - auto send(const NetMessageT& msg, ArgTs&&... args) + auto send(const NetMessageT& msg, const timeout_drtn_t& timeout = defaultSendTimeout, ArgTs&&... args) { + return _implUptr->send(msg, timeout, std::forward(args)...); } template - NetMessageT receive(ArgTs&&... args) + NetMessageT receive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args) { + return _implUptr->receive(timeout, std::forward(args)...); } template auto close(ArgTs&&... args) { + return _implUptr->close(std::forward(args)...); } }; + } // namespace adc