#pragma once #include #include "http.h" class TInet64StreamSocket: public TStreamSocket { protected: TInet64StreamSocket(const TInet64StreamSocket& parent, SOCKET fd) : TStreamSocket(fd) , AF(parent.AF) { } public: TInet64StreamSocket(int af = {}) { CreateSocket(af); } std::shared_ptr MakeAddress(const TString& address, int port) { if (!address) { if (AF == AF_INET6) { return std::make_shared("::", port); } else { return std::make_shared(INADDR_ANY, port); } } if (NHttp::IsIPv6(address)) { return std::make_shared(address.data(), port); } else { return std::make_shared(address.data(), port); } } static std::shared_ptr MakeAddress(const sockaddr_storage& storage) { std::shared_ptr addr; switch (storage.ss_family) { case AF_INET: addr = std::make_shared(); break; case AF_INET6: addr = std::make_shared(); break; } if (addr) { memcpy(addr->SockAddr(), &storage, addr->Size()); } return addr; } std::optional Accept(std::shared_ptr& acceptedAddr) { sockaddr_storage addrStorage = {}; socklen_t addrLen = sizeof(addrStorage); SOCKET s = accept((SOCKET)*this, reinterpret_cast(&addrStorage), &addrLen); if (s == INVALID_SOCKET) { return {}; } acceptedAddr = MakeAddress(addrStorage); return TInet64StreamSocket(*this, s); } protected: int AF = 0; void CreateSocket(int af) { SOCKET s; if (af == 0) { s = socket(AF = AF_INET6, SOCK_STREAM, 0); if (s < 0) { s = socket(AF = AF_INET, SOCK_STREAM, 0); } } else { s = socket(AF = af, SOCK_STREAM, 0); } if (AF == AF_INET6) { SetSockOpt(s, SOL_SOCKET, IPV6_V6ONLY, (int)false); } TSocketHolder sock(s); sock.Swap(*this); } };