#pragma once // //primary header for work with asio // #include <util/generic/ptr.h> #include <util/generic/string.h> #include <util/generic/vector.h> #include <util/network/socket.h> #include <util/network/endpoint.h> #include <util/system/error.h> #include <util/stream/output.h> #include <functional> #include <library/cpp/dns/cache.h> //#define DEBUG_ASIO class TContIOVector; namespace NAsio { class TErrorCode { public: inline TErrorCode(int val = 0) noexcept : Val_(val) { } typedef void (*TUnspecifiedBoolType)(); static void UnspecifiedBoolTrue() { } //safe cast to bool value operator TUnspecifiedBoolType() const noexcept { // true if error return Val_ == 0 ? nullptr : UnspecifiedBoolTrue; } bool operator!() const noexcept { return Val_ == 0; } void Assign(int val) noexcept { Val_ = val; } int Value() const noexcept { return Val_; } TString Text() const { if (!Val_) { return TString(); } return LastSystemErrorText(Val_); } void Check() { if (Val_) { throw TSystemError(Val_); } } private: int Val_; }; //wrapper for TInstant, for enabling use TDuration (+TInstant::Now()) as deadline class TDeadline: public TInstant { public: TDeadline() : TInstant(TInstant::Max()) { } TDeadline(const TInstant& t) : TInstant(t) { } TDeadline(const TDuration& d) : TInstant(TInstant::Now() + d) { } }; class IHandlingContext { public: virtual ~IHandlingContext() { } //if handler throw exception, call this function be ignored virtual void ContinueUseHandler(TDeadline deadline = TDeadline()) = 0; }; typedef std::function<void()> TCompletionHandler; class TIOService: public TNonCopyable { public: TIOService(); ~TIOService(); void Run(); void Post(TCompletionHandler); //call handler in Run() thread-executor void Abort(); //in Run() all exist async i/o operations + timers receive error = ECANCELED, Run() exited //counterpart boost::asio::io_service::work class TWork { public: TWork(TWork&); TWork(TIOService&); ~TWork(); private: void operator=(const TWork&); //disable TIOService& Srv_; }; class TImpl; TImpl& GetImpl() noexcept { return *Impl_; } private: THolder<TImpl> Impl_; }; class TDeadlineTimer: public TNonCopyable { public: typedef std::function<void(const TErrorCode& err, IHandlingContext&)> THandler; TDeadlineTimer(TIOService&) noexcept; ~TDeadlineTimer(); void AsyncWaitExpireAt(TDeadline, THandler); void Cancel(); TIOService& GetIOService() const noexcept { return Srv_; } class TImpl; private: TIOService& Srv_; TImpl* Impl_; }; class TTcpSocket: public TNonCopyable { public: class IBuffers { public: virtual ~IBuffers() { } virtual TContIOVector* GetIOvec() = 0; }; typedef TAutoPtr<IBuffers> TSendedData; typedef std::function<void(const TErrorCode& err, IHandlingContext&)> THandler; typedef THandler TConnectHandler; typedef std::function<void(const TErrorCode& err, size_t amount, IHandlingContext&)> TWriteHandler; typedef std::function<void(const TErrorCode& err, size_t amount, IHandlingContext&)> TReadHandler; typedef THandler TPollHandler; enum TShutdownMode { ShutdownReceive = SHUT_RD, ShutdownSend = SHUT_WR, ShutdownBoth = SHUT_RDWR }; TTcpSocket(TIOService&) noexcept; ~TTcpSocket(); void AsyncConnect(const TEndpoint& ep, TConnectHandler, TDeadline deadline = TDeadline()); void AsyncWrite(TSendedData&, TWriteHandler, TDeadline deadline = TDeadline()); void AsyncWrite(TContIOVector* buff, TWriteHandler, TDeadline deadline = TDeadline()); void AsyncWrite(const void* buff, size_t size, TWriteHandler, TDeadline deadline = TDeadline()); void AsyncRead(void* buff, size_t size, TReadHandler, TDeadline deadline = TDeadline()); void AsyncReadSome(void* buff, size_t size, TReadHandler, TDeadline deadline = TDeadline()); void AsyncPollWrite(TPollHandler, TDeadline deadline = TDeadline()); void AsyncPollRead(TPollHandler, TDeadline deadline = TDeadline()); void AsyncCancel(); //sync, but non blocked methods size_t WriteSome(TContIOVector&, TErrorCode&) noexcept; size_t WriteSome(const void* buff, size_t size, TErrorCode&) noexcept; size_t ReadSome(void* buff, size_t size, TErrorCode&) noexcept; bool IsOpen() const noexcept; void Shutdown(TShutdownMode mode, TErrorCode& ec); TIOService& GetIOService() const noexcept { return Srv_; } SOCKET Native() const noexcept; TEndpoint RemoteEndpoint() const; inline size_t WriteSome(TContIOVector& v) { TErrorCode ec; size_t n = WriteSome(v, ec); ec.Check(); return n; } inline size_t WriteSome(const void* buff, size_t size) { TErrorCode ec; size_t n = WriteSome(buff, size, ec); ec.Check(); return n; } inline size_t ReadSome(void* buff, size_t size) { TErrorCode ec; size_t n = ReadSome(buff, size, ec); ec.Check(); return n; } void Shutdown(TShutdownMode mode) { TErrorCode ec; Shutdown(mode, ec); ec.Check(); } class TImpl; TImpl& GetImpl() const noexcept { return *Impl_; } private: TIOService& Srv_; TIntrusivePtr<TImpl> Impl_; }; class TTcpAcceptor: public TNonCopyable { public: typedef std::function<void(const TErrorCode& err, IHandlingContext&)> TAcceptHandler; TTcpAcceptor(TIOService&) noexcept; ~TTcpAcceptor(); void Bind(TEndpoint&, TErrorCode&) noexcept; void Listen(int backlog, TErrorCode&) noexcept; void AsyncAccept(TTcpSocket&, TAcceptHandler, TDeadline deadline = TDeadline()); void AsyncCancel(); inline void Bind(TEndpoint& ep) { TErrorCode ec; Bind(ep, ec); ec.Check(); } inline void Listen(int backlog) { TErrorCode ec; Listen(backlog, ec); ec.Check(); } TIOService& GetIOService() const noexcept { return Srv_; } class TImpl; TImpl& GetImpl() const noexcept { return *Impl_; } private: TIOService& Srv_; TIntrusivePtr<TImpl> Impl_; }; }