#pragma once #include #include #include #include #include #include #include #include #include #include #include class TAddrList: public TVector { private: using TBase = TVector; public: //msvc doesn't support base class constructor inheritance TAddrList() = default; template TAddrList(T&& arg) : TBase(std::forward(arg)) { } template TAddrList(T1&& arg1, T2&& arg2) : TBase(std::forward(arg1), std::forward(arg2)) { } TAddrList(std::initializer_list list) : TBase(list) { } static TAddrList MakeV4Addr(ui32 ip, TIpPort port) { return TAddrList({new NAddr::TIPv4Addr(TIpAddress(htonl(ip), htons(port)))}); } std::pair GetV4Addr() const { for (const auto& addrRef : *this) { const sockaddr* sa = addrRef->Addr(); if (sa->sa_family == AF_INET) { const sockaddr_in* sin = reinterpret_cast(sa); return std::make_pair(ntohl(sin->sin_addr.s_addr), ntohs(sin->sin_port)); } } return std::make_pair(0, 0); } }; class TSimpleSocketHandler { public: TSimpleSocketHandler() = default; int Good() const { return static_cast(Socket); } int Connect(const TAddrList& addrs, TDuration timeout) { try { for (const auto& item : addrs) { const sockaddr* sa = item->Addr(); TSocketHolder s(socket(sa->sa_family, SOCK_STREAM, 0)); if (s.Closed()) { continue; } #ifndef WIN32 if (fcntl(s, F_SETFD, FD_CLOEXEC)) // no inherit on fork()/exec() return errno ? errno : EBADF; #endif if (connect(s, sa, item->Len())) { s.Close(); continue; } Socket.Reset(new TSocket(s.Release())); Socket->SetSocketTimeout(timeout.Seconds(), timeout.MilliSecondsOfSecond()); Socket->SetZeroLinger(); Socket->SetKeepAlive(true); return 0; } } catch (...) { return EBADF; } return errno ? errno : EBADF; } void Disconnect() { if (!Socket) return; Socket->ShutDown(SHUT_RDWR); Socket.Destroy(); } void SetSocket(SOCKET fd) { Socket.Reset(new TSocket(fd)); } void shutdown() { Socket->ShutDown(SHUT_WR); } int send(const void* message, size_t messlen) { return ((ssize_t)messlen == Socket->Send(message, messlen)); } int peek() { char buf[1]; return (1 == recv(*Socket, buf, 1, MSG_PEEK)); } ssize_t read(void* buffer, size_t buflen) { return Socket->Recv(buffer, buflen); } THolder PickOutSocket() { return std::move(Socket); } protected: THolder Socket; };