socket.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #pragma once
  2. #include <util/system/platform.h>
  3. #include <util/generic/noncopyable.h>
  4. #include <util/generic/ptr.h>
  5. #include <util/network/init.h>
  6. #include <util/system/defaults.h>
  7. #include <util/system/hp_timer.h>
  8. #include "udp_recv_packet.h"
  9. #include "protocols.h"
  10. #include <sys/uio.h>
  11. namespace NNetlibaSocket {
  12. typedef iovec TIoVec;
  13. #ifdef _win32_
  14. struct TMsgHdr {
  15. void* msg_name; /* optional address */
  16. int msg_namelen; /* size of address */
  17. TIoVec* msg_iov; /* scatter/gather array */
  18. int msg_iovlen; /* # elements in msg_iov */
  19. int Tos; // netlib_socket extension
  20. };
  21. #else
  22. #include <sys/socket.h>
  23. typedef msghdr TMsgHdr;
  24. #endif
  25. // equal to glibc 2.14 mmsghdr definition, defined for windows and darwin compatibility
  26. struct TMMsgHdr {
  27. TMsgHdr msg_hdr;
  28. unsigned int msg_len;
  29. };
  30. #if defined(_linux_)
  31. #include <linux/version.h>
  32. #include <features.h>
  33. // sendmmsg was added in glibc 2.14 and linux 3.0
  34. #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 14 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
  35. #include <sys/socket.h> // sendmmsg
  36. static_assert(sizeof(TMMsgHdr) == sizeof(mmsghdr), "expect sizeof(TMMsgHdr) == sizeof(mmsghdr)");
  37. #endif
  38. #endif
  39. #ifdef _win32_
  40. const size_t TOS_BUFFER_SIZE = sizeof(int);
  41. const size_t CTRL_BUFFER_SIZE = 32;
  42. #else
  43. #if defined(_darwin_)
  44. #define Y_DARWIN_ALIGN32(p) ((__darwin_size_t)((__darwin_size_t)(p) + __DARWIN_ALIGNBYTES32) & ~__DARWIN_ALIGNBYTES32)
  45. #define Y_CMSG_SPACE(l) (Y_DARWIN_ALIGN32(sizeof(struct cmsghdr)) + Y_DARWIN_ALIGN32(l))
  46. #else
  47. #define Y_CMSG_SPACE(l) CMSG_SPACE(l)
  48. #endif
  49. constexpr size_t TOS_BUFFER_SIZE = Y_CMSG_SPACE(sizeof(int));
  50. constexpr size_t CTRL_BUFFER_SIZE = Y_CMSG_SPACE(sizeof(int)) + Y_CMSG_SPACE(sizeof(struct in6_pktinfo));
  51. #endif
  52. ///////////////////////////////////////////////////////////////////////////////
  53. // Warning: every variable (tosBuffer, data, addr, iov) passed and returned from these functions must exist until actual send!!!
  54. void* CreateTos(const ui8 tos, void* tosBuffer);
  55. TIoVec CreateIoVec(char* data, const size_t dataSize);
  56. TMsgHdr CreateSendMsgHdr(const sockaddr_in6& addr, const TIoVec& iov, void* tosBuffer);
  57. TMsgHdr CreateRecvMsgHdr(sockaddr_in6* addrBuf, const TIoVec& iov, void* ctrlBuffer = nullptr);
  58. TMsgHdr* AddSockAuxData(TMsgHdr* header, const ui8 tos, const sockaddr_in6& addr, void* buffer, size_t bufferSize);
  59. ///////////////////////////////////////////////////////////////////////////////
  60. //returns false if TOS wasn't readed and do not touch *tos
  61. bool ReadTos(const TMsgHdr& msgHdr, ui8* tos);
  62. bool ExtractDestinationAddress(TMsgHdr& msgHdr, sockaddr_in6* addrBuf);
  63. ///////////////////////////////////////////////////////////////////////////////
  64. // currently netliba v6 version id is any number which's not equal to NETLIBA_V12_VERSION
  65. enum { NETLIBA_ANY_VERSION = -1,
  66. NETLIBA_V12_VERSION = 112 };
  67. enum EFragFlag {
  68. FF_ALLOW_FRAG,
  69. FF_DONT_FRAG
  70. };
  71. ///////////////////////////////////////////////////////////////////////////////
  72. class ISocket: public TNonCopyable, public TThrRefBase {
  73. public:
  74. ~ISocket() override {
  75. }
  76. virtual int Open(int port) = 0;
  77. virtual void Close() = 0;
  78. virtual bool IsValid() const = 0;
  79. virtual const sockaddr_in6& GetSelfAddress() const = 0;
  80. virtual int GetNetworkOrderPort() const = 0;
  81. virtual int GetPort() const = 0;
  82. virtual int GetSockOpt(int level, int option_name, void* option_value, socklen_t* option_len) = 0;
  83. // send all packets to this and only this address by default
  84. virtual int Connect(const struct sockaddr* address, socklen_t address_len) = 0;
  85. virtual void Wait(float timeoutSec, int netlibaVersion = NETLIBA_ANY_VERSION) const = 0;
  86. virtual void CancelWait(int netlibaVersion = NETLIBA_ANY_VERSION) = 0;
  87. virtual void CancelWaitHost(const sockaddr_in6 address) = 0;
  88. virtual bool IsSendMMsgSupported() const = 0;
  89. virtual int SendMMsg(struct TMMsgHdr* msgvec, unsigned int vlen, unsigned int flags) = 0;
  90. virtual ssize_t SendMsg(const TMsgHdr* hdr, int flags, const EFragFlag frag) = 0;
  91. virtual bool IsRecvMsgSupported() const = 0;
  92. virtual ssize_t RecvMsg(TMsgHdr* hdr, int flags) = 0;
  93. virtual TUdpRecvPacket* Recv(sockaddr_in6* srcAddr, sockaddr_in6* dstAddr, int netlibaVersion = NETLIBA_ANY_VERSION) = 0;
  94. virtual bool IncreaseSendBuff() = 0;
  95. virtual int GetSendSysSocketSize() = 0;
  96. virtual void SetRecvLagTime(NHPTimer::STime time) = 0;
  97. };
  98. TIntrusivePtr<ISocket> CreateSocket(); // not thread safe!
  99. TIntrusivePtr<ISocket> CreateDualStackSocket(); // has thread safe send/recv methods
  100. // this function was added mostly for testing
  101. TIntrusivePtr<ISocket> CreateBestRecvSocket();
  102. }