#pragma once #include "util.h" #include "Stream.h" #include "AddrInfo.h" #include "Resolver.h" #include "backend/TcpImpl.h" #include namespace panda { namespace unievent { struct ITcpListener : IStreamListener {}; struct ITcpSelfListener : IStreamSelfListener {}; struct Tcp : virtual Stream, AllocatedObject { using TcpImpl = backend::TcpImpl; using Flags = TcpImpl::Flags; static const HandleType TYPE; static const AddrInfoHints defhints; Tcp (const LoopSP& loop = Loop::default_loop(), int domain = AF_UNSPEC); ~Tcp () { panda_log_dtor(); } const HandleType& type () const override; virtual excepted open (sock_t socket, Ownership = Ownership::TRANSFER); virtual excepted bind (const net::SockAddr&, unsigned flags = 0); virtual excepted bind (string_view host, uint16_t port, const AddrInfoHints& hints = defhints, unsigned flags = 0); TcpConnectRequestSP connect (); TcpConnectRequestSP connect (const net::SockAddr& sa, uint64_t timeout = 0); TcpConnectRequestSP connect (const string& host, uint16_t port, uint64_t timeout = 0, const AddrInfoHints& hints = defhints); virtual void connect (const TcpConnectRequestSP&); excepted sockaddr () const override; excepted peeraddr () const override; excepted set_nodelay (bool enable) { return make_excepted(impl()->set_nodelay(enable)); } excepted set_keepalive (bool enable, unsigned int delay) { return make_excepted(impl()->set_keepalive(enable, delay)); } excepted set_simultaneous_accepts (bool enable) { return make_excepted(impl()->set_simultaneous_accepts(enable)); } excepted socket () const; void setsockopt (int level, int optname, const void* optval, int optlen) { unievent::setsockopt(socket().value(), level, optname, optval, optlen); } static excepted, ErrorCode> pair (const LoopSP& = Loop::default_loop(), int type = SOCK_STREAM, int proto = PF_UNSPEC); static excepted, ErrorCode> pair (const TcpSP&, const TcpSP&, int type = SOCK_STREAM, int proto = PF_UNSPEC); protected: StreamSP create_connection () override; private: friend TcpConnectRequest; int domain; backend::TcpImpl* impl () const { return static_cast(BackendHandle::impl()); } HandleImpl* new_impl () override; }; struct TcpConnectRequest : ConnectRequest, AllocatedObject { net::SockAddr addr; string host; uint16_t port; bool cached; AddrInfoHints hints; TcpConnectRequest (Tcp* h = nullptr) : port(), cached(true), handle(h) {} TcpConnectRequestSP to (const string& host, uint16_t port, const AddrInfoHints& hints = Tcp::defhints) { this->host = host; this->port = port; this->hints = hints; return this; } TcpConnectRequestSP to (const net::SockAddr& val) { addr = val; return this; } TcpConnectRequestSP timeout (uint64_t val) { this->ConnectRequest::timeout = val; return this; } TcpConnectRequestSP on_connect (const Stream::connect_fn& val) { event.add(val); return this; } TcpConnectRequestSP use_cache (bool val) { cached = val; return this; } TcpConnectRequestSP set_hints (const AddrInfoHints& val) { hints = val; return this; } TcpConnectRequestSP run () { handle->connect(this); return this; } private: friend Tcp; friend StreamFilter; Tcp* handle; Resolver::RequestSP resolve_request; void set (Tcp* h) { handle = h; ConnectRequest::set(h); } void exec () override; void finalize_connect (); void handle_event (const ErrorCode&) override; }; inline TcpConnectRequestSP Tcp::connect () { return new TcpConnectRequest(this); } inline TcpConnectRequestSP Tcp::connect (const net::SockAddr& addr, uint64_t timeout) { return connect()->to(addr)->timeout(timeout)->run(); } inline TcpConnectRequestSP Tcp::connect (const string& host, uint16_t port, uint64_t timeout, const AddrInfoHints& hints) { return connect()->to(host, port, hints)->timeout(timeout)->run(); } std::ostream& operator<< (std::ostream&, const Tcp&); std::ostream& operator<< (std::ostream&, const TcpConnectRequest&); }}