diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/http/fetch/sockhandler.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/http/fetch/sockhandler.h')
-rw-r--r-- | library/cpp/http/fetch/sockhandler.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/library/cpp/http/fetch/sockhandler.h b/library/cpp/http/fetch/sockhandler.h new file mode 100644 index 0000000000..e18149f657 --- /dev/null +++ b/library/cpp/http/fetch/sockhandler.h @@ -0,0 +1,130 @@ +#pragma once + +#include <library/cpp/logger/all.h> + +#include <util/generic/buffer.h> +#include <util/generic/map.h> +#include <util/generic/vector.h> +#include <util/network/address.h> +#include <util/network/ip.h> +#include <util/network/socket.h> +#include <util/system/mutex.h> +#include <util/system/yassert.h> + +#include <cerrno> +#include <util/generic/noncopyable.h> + +class TAddrList: public TVector<NAddr::IRemoteAddrRef> { +private: + using TBase = TVector<NAddr::IRemoteAddrRef>; + +public: + //msvc doesn't support base class constructor inheritance + TAddrList() = default; + + template <typename T> + TAddrList(T&& arg) + : TBase(std::forward<T>(arg)) + { + } + + template <typename T1, typename T2> + TAddrList(T1&& arg1, T2&& arg2) + : TBase(std::forward<T1>(arg1), std::forward<T2>(arg2)) + { + } + + TAddrList(std::initializer_list<NAddr::IRemoteAddrRef> list) + : TBase(list) + { + } + + static TAddrList MakeV4Addr(ui32 ip, TIpPort port) { + return TAddrList({new NAddr::TIPv4Addr(TIpAddress(htonl(ip), htons(port)))}); + } + + std::pair<ui32, TIpPort> GetV4Addr() const { + for (const auto& addrRef : *this) { + const sockaddr* sa = addrRef->Addr(); + if (sa->sa_family == AF_INET) { + const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(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<bool>(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<TSocket> PickOutSocket() { + return std::move(Socket); + } + +protected: + THolder<TSocket> Socket; +}; |