http_proxy_sock64.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #pragma once
  2. #include <util/network/sock.h>
  3. #include "http.h"
  4. class TInet64StreamSocket: public TStreamSocket {
  5. protected:
  6. TInet64StreamSocket(const TInet64StreamSocket& parent, SOCKET fd)
  7. : TStreamSocket(fd)
  8. , AF(parent.AF)
  9. {
  10. }
  11. public:
  12. TInet64StreamSocket(int af = {}) {
  13. CreateSocket(af);
  14. }
  15. std::shared_ptr<ISockAddr> MakeAddress(const TString& address, int port) {
  16. if (!address) {
  17. if (AF == AF_INET6) {
  18. return std::make_shared<TSockAddrInet6>("::", port);
  19. } else {
  20. return std::make_shared<TSockAddrInet>(INADDR_ANY, port);
  21. }
  22. }
  23. if (NHttp::IsIPv6(address)) {
  24. return std::make_shared<TSockAddrInet6>(address.data(), port);
  25. } else if (NHttp::IsIPv4(address)) {
  26. return std::make_shared<TSockAddrInet>(address.data(), port);
  27. }
  28. struct addrinfo hints = {
  29. .ai_flags = AI_PASSIVE,
  30. .ai_family = AF,
  31. .ai_socktype = SOCK_STREAM,
  32. };
  33. struct addrinfo* gai_res = nullptr;
  34. int gai_ret = getaddrinfo(address.data(), nullptr, &hints, &gai_res);
  35. std::shared_ptr<ISockAddr> result;
  36. if (gai_ret == 0 && gai_res->ai_addr) {
  37. switch (gai_res->ai_addr->sa_family) {
  38. case AF_INET6: {
  39. std::shared_ptr<TSockAddrInet6> resultIp6 = std::make_shared<TSockAddrInet6>();
  40. if (resultIp6->Size() >= gai_res->ai_addrlen) {
  41. memcpy(resultIp6->SockAddr(), gai_res->ai_addr, gai_res->ai_addrlen);
  42. resultIp6->SetPort(port);
  43. result = std::move(resultIp6);
  44. }
  45. }
  46. break;
  47. case AF_INET: {
  48. std::shared_ptr<TSockAddrInet> resultIp4 = std::make_shared<TSockAddrInet>();
  49. if (resultIp4->Size() >= gai_res->ai_addrlen) {
  50. memcpy(resultIp4->SockAddr(), gai_res->ai_addr, gai_res->ai_addrlen);
  51. resultIp4->SetPort(port);
  52. result = std::move(resultIp4);
  53. }
  54. }
  55. break;
  56. }
  57. }
  58. if (gai_res) {
  59. freeaddrinfo(gai_res);
  60. }
  61. if (result) {
  62. return result;
  63. }
  64. throw yexception() << "Unable to resolve address " << address;
  65. }
  66. static int GuessAddressFamily(const TString& address) {
  67. if (!address) {
  68. return 0;
  69. }
  70. if (NHttp::IsIPv6(address)) {
  71. return AF_INET6;
  72. } else if (NHttp::IsIPv4(address)) {
  73. return AF_INET;
  74. }
  75. struct addrinfo hints = {
  76. .ai_flags = AI_PASSIVE,
  77. .ai_family = 0,
  78. .ai_socktype = SOCK_STREAM,
  79. };
  80. struct addrinfo* gai_res = nullptr;
  81. int gai_ret = getaddrinfo(address.data(), nullptr, &hints, &gai_res);
  82. if (gai_ret == 0 && gai_res->ai_addr) {
  83. switch (gai_res->ai_addr->sa_family) {
  84. case AF_INET:
  85. case AF_INET6:
  86. return gai_res->ai_addr->sa_family;
  87. }
  88. }
  89. if (gai_res) {
  90. freeaddrinfo(gai_res);
  91. }
  92. return 0;
  93. }
  94. static std::shared_ptr<ISockAddr> MakeAddress(const sockaddr_storage& storage) {
  95. std::shared_ptr<ISockAddr> addr;
  96. switch (storage.ss_family) {
  97. case AF_INET:
  98. addr = std::make_shared<TSockAddrInet>();
  99. break;
  100. case AF_INET6:
  101. addr = std::make_shared<TSockAddrInet6>();
  102. break;
  103. }
  104. if (addr) {
  105. memcpy(addr->SockAddr(), &storage, addr->Size());
  106. }
  107. return addr;
  108. }
  109. std::optional<TInet64StreamSocket> Accept(std::shared_ptr<ISockAddr>& acceptedAddr) {
  110. sockaddr_storage addrStorage = {};
  111. socklen_t addrLen = sizeof(addrStorage);
  112. SOCKET s = accept((SOCKET)*this, reinterpret_cast<sockaddr*>(&addrStorage), &addrLen);
  113. if (s == INVALID_SOCKET) {
  114. return {};
  115. }
  116. acceptedAddr = MakeAddress(addrStorage);
  117. return TInet64StreamSocket(*this, s);
  118. }
  119. protected:
  120. int AF = AF_UNSPEC;
  121. void CreateSocket(int af) {
  122. SOCKET s;
  123. if (af == 0) {
  124. s = socket(AF = AF_INET6, SOCK_STREAM, 0);
  125. if (s < 0) {
  126. s = socket(AF = AF_INET, SOCK_STREAM, 0);
  127. }
  128. } else {
  129. s = socket(AF = af, SOCK_STREAM, 0);
  130. }
  131. if (AF == AF_INET6) {
  132. SetSockOpt(s, SOL_SOCKET, IPV6_V6ONLY, (int)false);
  133. }
  134. TSocketHolder sock(s);
  135. sock.Swap(*this);
  136. }
  137. };