123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626 |
- #pragma once
- #include <util/folder/path.h>
- #include <util/system/defaults.h>
- #include <util/string/cast.h>
- #include <util/stream/output.h>
- #include <util/system/sysstat.h>
- #if defined(_win_) || defined(_cygwin_)
- #include <util/system/file.h>
- #else
- #include <sys/un.h>
- #include <sys/stat.h>
- #endif //_win_
- #include "init.h"
- #include "ip.h"
- #include "socket.h"
- constexpr ui16 DEF_LOCAL_SOCK_MODE = 00644;
- // Base abstract class for socket address
- struct ISockAddr {
- virtual ~ISockAddr() = default;
- // Max size of the address that we can store (arg of recvfrom)
- virtual socklen_t Size() const = 0;
- // Real length of the address (arg of sendto)
- virtual socklen_t Len() const = 0;
- // cast to sockaddr* to pass to any syscall
- virtual sockaddr* SockAddr() = 0;
- virtual const sockaddr* SockAddr() const = 0;
- // address in human readable form
- virtual TString ToString() const = 0;
- protected:
- // below are the implemetation methods that can be called by T*Socket classes
- friend class TBaseSocket;
- friend class TDgramSocket;
- friend class TStreamSocket;
- virtual int ResolveAddr() const {
- // usually it's nothing to do here
- return 0;
- }
- virtual int Bind(SOCKET s, ui16 mode) const = 0;
- };
- #if defined(_win_) || defined(_cygwin_)
- #define YAF_LOCAL AF_INET
- struct TSockAddrLocal: public ISockAddr {
- TSockAddrLocal() {
- Clear();
- }
- TSockAddrLocal(const char* path) {
- Set(path);
- }
- socklen_t Size() const {
- return sizeof(sockaddr_in);
- }
- socklen_t Len() const {
- return Size();
- }
- inline void Clear() noexcept {
- Zero(in);
- Zero(Path);
- }
- inline void Set(const char* path) noexcept {
- Clear();
- in.sin_family = AF_INET;
- in.sin_addr.s_addr = IpFromString("127.0.0.1");
- in.sin_port = 0;
- strlcpy(Path, path, PathSize);
- }
- inline void Set(TStringBuf path) noexcept {
- Clear();
- in.sin_family = AF_INET;
- in.sin_addr.s_addr = IpFromString("127.0.0.1");
- in.sin_port = 0;
- strlcpy(Path, path.data(), Min(PathSize, path.size() + 1));
- }
- sockaddr* SockAddr() {
- return (struct sockaddr*)(&in);
- }
- const sockaddr* SockAddr() const {
- return (const struct sockaddr*)(&in);
- }
- TString ToString() const {
- return TString(Path);
- }
- TFsPath ToPath() const {
- return TFsPath(Path);
- }
- int ResolveAddr() const {
- if (in.sin_port == 0) {
- int ret = 0;
- // 1. open file
- TFileHandle f(Path, OpenExisting | RdOnly);
- if (!f.IsOpen())
- return -errno;
- // 2. read the port from file
- ret = f.Read(&in.sin_port, sizeof(in.sin_port));
- if (ret != sizeof(in.sin_port))
- return -(errno ? errno : EFAULT);
- }
- return 0;
- }
- int Bind(SOCKET s, ui16 mode) const {
- Y_UNUSED(mode);
- int ret = 0;
- // 1. open file
- TFileHandle f(Path, CreateAlways | WrOnly);
- if (!f.IsOpen())
- return -errno;
- // 2. find port and bind to it
- in.sin_port = 0;
- ret = bind(s, SockAddr(), Len());
- if (ret != 0)
- return -WSAGetLastError();
- int size = Size();
- ret = getsockname(s, (struct sockaddr*)(&in), &size);
- if (ret != 0)
- return -WSAGetLastError();
- // 3. write port to file
- ret = f.Write(&(in.sin_port), sizeof(in.sin_port));
- if (ret != sizeof(in.sin_port))
- return -errno;
- return 0;
- }
- static constexpr size_t PathSize = 128;
- mutable struct sockaddr_in in;
- char Path[PathSize];
- };
- #else
- #define YAF_LOCAL AF_LOCAL
- struct TSockAddrLocal: public sockaddr_un, public ISockAddr {
- TSockAddrLocal() {
- Clear();
- }
- TSockAddrLocal(TStringBuf path) {
- Set(path);
- }
- TSockAddrLocal(const char* path) {
- Set(path);
- }
- socklen_t Size() const override {
- return sizeof(sockaddr_un);
- }
- socklen_t Len() const override {
- return strlen(sun_path) + 2;
- }
- inline void Clear() noexcept {
- Zero(*(sockaddr_un*)this);
- }
- inline void Set(const char* path) noexcept {
- Clear();
- sun_family = AF_UNIX;
- strlcpy(sun_path, path, sizeof(sun_path));
- }
- inline void Set(TStringBuf path) noexcept {
- Clear();
- sun_family = AF_UNIX;
- strlcpy(sun_path, path.data(), Min(sizeof(sun_path), path.size() + 1));
- }
- sockaddr* SockAddr() override {
- return (struct sockaddr*)(struct sockaddr_un*)this;
- }
- const sockaddr* SockAddr() const override {
- return (const struct sockaddr*)(const struct sockaddr_un*)this;
- }
- TString ToString() const override {
- return TString(sun_path);
- }
- TFsPath ToPath() const {
- return TFsPath(sun_path);
- }
- int Bind(SOCKET s, ui16 mode) const override {
- (void)unlink(sun_path);
- int ret = bind(s, SockAddr(), Len());
- if (ret < 0)
- return -errno;
- ret = Chmod(sun_path, mode);
- if (ret < 0)
- return -errno;
- return 0;
- }
- };
- #endif // _win_
- struct TSockAddrInet: public sockaddr_in, public ISockAddr {
- TSockAddrInet() {
- Clear();
- }
- TSockAddrInet(TIpHost ip, TIpPort port) {
- Set(ip, port);
- }
- TSockAddrInet(const char* ip, TIpPort port) {
- Set(IpFromString(ip), port);
- }
- socklen_t Size() const override {
- return sizeof(sockaddr_in);
- }
- socklen_t Len() const override {
- return Size();
- }
- inline void Clear() noexcept {
- Zero(*(sockaddr_in*)this);
- }
- inline void Set(TIpHost ip, TIpPort port) noexcept {
- Clear();
- sin_family = AF_INET;
- sin_addr.s_addr = ip;
- sin_port = HostToInet(port);
- }
- sockaddr* SockAddr() override {
- return (struct sockaddr*)(struct sockaddr_in*)this;
- }
- const sockaddr* SockAddr() const override {
- return (const struct sockaddr*)(const struct sockaddr_in*)this;
- }
- TString ToString() const override {
- return IpToString(sin_addr.s_addr) + ":" + ::ToString(InetToHost(sin_port));
- }
- int Bind(SOCKET s, ui16 mode) const override {
- Y_UNUSED(mode);
- int ret = bind(s, SockAddr(), Len());
- if (ret < 0)
- return -errno;
- socklen_t len = Len();
- if (getsockname(s, (struct sockaddr*)(SockAddr()), &len) < 0)
- return -WSAGetLastError();
- return 0;
- }
- TIpHost GetIp() const noexcept {
- return sin_addr.s_addr;
- }
- TIpPort GetPort() const noexcept {
- return InetToHost(sin_port);
- }
- void SetPort(TIpPort port) noexcept {
- sin_port = HostToInet(port);
- }
- };
- struct TSockAddrInet6: public sockaddr_in6, public ISockAddr {
- TSockAddrInet6() {
- Clear();
- }
- TSockAddrInet6(const char* ip6, const TIpPort port) {
- Set(ip6, port);
- }
- socklen_t Size() const override {
- return sizeof(sockaddr_in6);
- }
- socklen_t Len() const override {
- return Size();
- }
- inline void Clear() noexcept {
- Zero(*(sockaddr_in6*)this);
- }
- inline void Set(const char* ip6, const TIpPort port) noexcept {
- Clear();
- sin6_family = AF_INET6;
- inet_pton(AF_INET6, ip6, &sin6_addr);
- sin6_port = HostToInet(port);
- }
- sockaddr* SockAddr() override {
- return (struct sockaddr*)(struct sockaddr_in6*)this;
- }
- const sockaddr* SockAddr() const override {
- return (const struct sockaddr*)(const struct sockaddr_in6*)this;
- }
- TString ToString() const override {
- return "[" + GetIp() + "]:" + ::ToString(InetToHost(sin6_port));
- }
- int Bind(SOCKET s, ui16 mode) const override {
- Y_UNUSED(mode);
- int ret = bind(s, SockAddr(), Len());
- if (ret < 0) {
- return -errno;
- }
- socklen_t len = Len();
- if (getsockname(s, (struct sockaddr*)(SockAddr()), &len) < 0) {
- return -WSAGetLastError();
- }
- return 0;
- }
- TString GetIp() const noexcept {
- char ip6[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, (void*)&sin6_addr, ip6, INET6_ADDRSTRLEN);
- return TString(ip6);
- }
- TIpPort GetPort() const noexcept {
- return InetToHost(sin6_port);
- }
- void SetPort(TIpPort port) noexcept {
- sin6_port = HostToInet(port);
- }
- };
- using TSockAddrLocalStream = TSockAddrLocal;
- using TSockAddrLocalDgram = TSockAddrLocal;
- using TSockAddrInetStream = TSockAddrInet;
- using TSockAddrInetDgram = TSockAddrInet;
- using TSockAddrInet6Stream = TSockAddrInet6;
- using TSockAddrInet6Dgram = TSockAddrInet6;
- class TBaseSocket: public TSocketHolder {
- protected:
- TBaseSocket(SOCKET fd)
- : TSocketHolder(fd)
- {
- }
- public:
- int Bind(const ISockAddr* addr, ui16 mode = DEF_LOCAL_SOCK_MODE) {
- return addr->Bind((SOCKET) * this, mode);
- }
- void CheckSock() {
- if ((SOCKET) * this == INVALID_SOCKET)
- ythrow TSystemError() << "no socket";
- }
- static ssize_t Check(ssize_t ret, const char* op = "") {
- if (ret < 0)
- ythrow TSystemError(-(int)ret) << "socket operation " << op;
- return ret;
- }
- };
- class TDgramSocket: public TBaseSocket {
- protected:
- TDgramSocket(SOCKET fd)
- : TBaseSocket(fd)
- {
- }
- public:
- ssize_t SendTo(const void* msg, size_t len, const ISockAddr* toAddr) {
- ssize_t ret = toAddr->ResolveAddr();
- if (ret < 0) {
- return -LastSystemError();
- }
- ret = sendto((SOCKET) * this, (const char*)msg, (int)len, 0, toAddr->SockAddr(), toAddr->Len());
- if (ret < 0) {
- return -LastSystemError();
- }
- return ret;
- }
- ssize_t RecvFrom(void* buf, size_t len, ISockAddr* fromAddr) {
- socklen_t fromSize = fromAddr->Size();
- const ssize_t ret = recvfrom((SOCKET) * this, (char*)buf, (int)len, 0, fromAddr->SockAddr(), &fromSize);
- if (ret < 0) {
- return -LastSystemError();
- }
- return ret;
- }
- };
- class TStreamSocket: public TBaseSocket {
- protected:
- explicit TStreamSocket(SOCKET fd)
- : TBaseSocket(fd)
- {
- }
- public:
- TStreamSocket()
- : TBaseSocket(INVALID_SOCKET)
- {
- }
- ssize_t Send(const void* msg, size_t len, int flags = 0) {
- const ssize_t ret = send((SOCKET) * this, (const char*)msg, (int)len, flags);
- if (ret < 0)
- return -errno;
- return ret;
- }
- ssize_t Recv(void* buf, size_t len, int flags = 0) {
- const ssize_t ret = recv((SOCKET) * this, (char*)buf, (int)len, flags);
- if (ret < 0)
- return -errno;
- return ret;
- }
- int Connect(const ISockAddr* addr) {
- int ret = addr->ResolveAddr();
- if (ret < 0)
- return -errno;
- ret = connect((SOCKET) * this, addr->SockAddr(), addr->Len());
- if (ret < 0)
- return -errno;
- return ret;
- }
- int Listen(int backlog) {
- int ret = listen((SOCKET) * this, backlog);
- if (ret < 0)
- return -errno;
- return ret;
- }
- int Accept(TStreamSocket* acceptedSock, ISockAddr* acceptedAddr = nullptr) {
- SOCKET s = INVALID_SOCKET;
- if (acceptedAddr) {
- socklen_t acceptedSize = acceptedAddr->Size();
- s = accept((SOCKET) * this, acceptedAddr->SockAddr(), &acceptedSize);
- } else {
- s = accept((SOCKET) * this, nullptr, nullptr);
- }
- if (s == INVALID_SOCKET)
- return -errno;
- TSocketHolder sock(s);
- acceptedSock->Swap(sock);
- return 0;
- }
- };
- class TLocalDgramSocket: public TDgramSocket {
- public:
- TLocalDgramSocket(SOCKET fd)
- : TDgramSocket(fd)
- {
- }
- TLocalDgramSocket()
- : TDgramSocket(socket(YAF_LOCAL, SOCK_DGRAM, 0))
- {
- }
- };
- class TInetDgramSocket: public TDgramSocket {
- public:
- TInetDgramSocket(SOCKET fd)
- : TDgramSocket(fd)
- {
- }
- TInetDgramSocket()
- : TDgramSocket(socket(AF_INET, SOCK_DGRAM, 0))
- {
- }
- };
- class TInet6DgramSocket: public TDgramSocket {
- public:
- TInet6DgramSocket(SOCKET fd)
- : TDgramSocket(fd)
- {
- }
- TInet6DgramSocket()
- : TDgramSocket(socket(AF_INET6, SOCK_DGRAM, 0))
- {
- }
- };
- class TLocalStreamSocket: public TStreamSocket {
- public:
- TLocalStreamSocket(SOCKET fd)
- : TStreamSocket(fd)
- {
- }
- TLocalStreamSocket()
- : TStreamSocket(socket(YAF_LOCAL, SOCK_STREAM, 0))
- {
- }
- };
- class TInetStreamSocket: public TStreamSocket {
- public:
- TInetStreamSocket(SOCKET fd)
- : TStreamSocket(fd)
- {
- }
- TInetStreamSocket()
- : TStreamSocket(socket(AF_INET, SOCK_STREAM, 0))
- {
- }
- };
- class TInet6StreamSocket: public TStreamSocket {
- public:
- TInet6StreamSocket(SOCKET fd)
- : TStreamSocket(fd)
- {
- }
- TInet6StreamSocket()
- : TStreamSocket(socket(AF_INET6, SOCK_STREAM, 0))
- {
- }
- };
- class TStreamSocketInput: public IInputStream {
- public:
- TStreamSocketInput(TStreamSocket* socket)
- : Socket(socket)
- {
- }
- void SetSocket(TStreamSocket* socket) {
- Socket = socket;
- }
- protected:
- TStreamSocket* Socket;
- size_t DoRead(void* buf, size_t len) override {
- Y_VERIFY(Socket, "TStreamSocketInput: socket isn't set");
- const ssize_t ret = Socket->Recv(buf, len);
- if (ret >= 0) {
- return (size_t)ret;
- }
- ythrow TSystemError(-(int)ret) << "can not read from socket input stream";
- }
- };
- class TStreamSocketOutput: public IOutputStream {
- public:
- TStreamSocketOutput(TStreamSocket* socket)
- : Socket(socket)
- {
- }
- void SetSocket(TStreamSocket* socket) {
- Socket = socket;
- }
- TStreamSocketOutput(TStreamSocketOutput&&) noexcept = default;
- TStreamSocketOutput& operator=(TStreamSocketOutput&&) noexcept = default;
- protected:
- TStreamSocket* Socket;
- void DoWrite(const void* buf, size_t len) override {
- Y_VERIFY(Socket, "TStreamSocketOutput: socket isn't set");
- const char* ptr = (const char*)buf;
- while (len) {
- const ssize_t ret = Socket->Send(ptr, len);
- if (ret < 0) {
- ythrow TSystemError(-(int)ret) << "can not write to socket output stream";
- }
- Y_ASSERT((size_t)ret <= len);
- len -= (size_t)ret;
- ptr += (size_t)ret;
- }
- }
- };
|