socket.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. // Copyright 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "socket.h"
  15. #include "rwmutex.h"
  16. #if defined(_WIN32)
  17. #include <winsock2.h>
  18. #include <ws2tcpip.h>
  19. #else
  20. #include <netdb.h>
  21. #include <netinet/in.h>
  22. #include <netinet/tcp.h>
  23. #include <sys/select.h>
  24. #include <sys/socket.h>
  25. #include <unistd.h>
  26. #endif
  27. #if defined(_WIN32)
  28. #include <atomic>
  29. namespace {
  30. std::atomic<int> wsaInitCount = {0};
  31. } // anonymous namespace
  32. #else
  33. #include <fcntl.h>
  34. #include <unistd.h>
  35. namespace {
  36. using SOCKET = int;
  37. } // anonymous namespace
  38. #endif
  39. namespace {
  40. constexpr SOCKET InvalidSocket = static_cast<SOCKET>(-1);
  41. void init() {
  42. #if defined(_WIN32)
  43. if (wsaInitCount++ == 0) {
  44. WSADATA winsockData;
  45. (void)WSAStartup(MAKEWORD(2, 2), &winsockData);
  46. }
  47. #endif
  48. }
  49. void term() {
  50. #if defined(_WIN32)
  51. if (--wsaInitCount == 0) {
  52. WSACleanup();
  53. }
  54. #endif
  55. }
  56. bool setBlocking(SOCKET s, bool blocking) {
  57. #if defined(_WIN32)
  58. u_long mode = blocking ? 0 : 1;
  59. return ioctlsocket(s, FIONBIO, &mode) == NO_ERROR;
  60. #else
  61. auto arg = fcntl(s, F_GETFL, nullptr);
  62. if (arg < 0) {
  63. return false;
  64. }
  65. arg = blocking ? (arg & ~O_NONBLOCK) : (arg | O_NONBLOCK);
  66. return fcntl(s, F_SETFL, arg) >= 0;
  67. #endif
  68. }
  69. bool errored(SOCKET s) {
  70. if (s == InvalidSocket) {
  71. return true;
  72. }
  73. char error = 0;
  74. socklen_t len = sizeof(error);
  75. getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len);
  76. return error != 0;
  77. }
  78. } // anonymous namespace
  79. class dap::Socket::Shared : public dap::ReaderWriter {
  80. public:
  81. static std::shared_ptr<Shared> create(const char* address, const char* port) {
  82. init();
  83. addrinfo hints = {};
  84. hints.ai_family = AF_INET;
  85. hints.ai_socktype = SOCK_STREAM;
  86. hints.ai_protocol = IPPROTO_TCP;
  87. hints.ai_flags = AI_PASSIVE;
  88. addrinfo* info = nullptr;
  89. getaddrinfo(address, port, &hints, &info);
  90. if (info) {
  91. auto socket =
  92. ::socket(info->ai_family, info->ai_socktype, info->ai_protocol);
  93. auto out = std::make_shared<Shared>(info, socket);
  94. out->setOptions();
  95. return out;
  96. }
  97. term();
  98. return nullptr;
  99. }
  100. Shared(SOCKET socket) : info(nullptr), s(socket) {}
  101. Shared(addrinfo* info, SOCKET socket) : info(info), s(socket) {}
  102. ~Shared() {
  103. if (info) {
  104. freeaddrinfo(info);
  105. }
  106. close();
  107. term();
  108. }
  109. template <typename FUNCTION>
  110. void lock(FUNCTION&& f) {
  111. RLock l(mutex);
  112. f(s, info);
  113. }
  114. void setOptions() {
  115. RLock l(mutex);
  116. if (s == InvalidSocket) {
  117. return;
  118. }
  119. int enable = 1;
  120. #if !defined(_WIN32)
  121. // Prevent sockets lingering after process termination, causing
  122. // reconnection issues on the same port.
  123. setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&enable, sizeof(enable));
  124. struct {
  125. int l_onoff; /* linger active */
  126. int l_linger; /* how many seconds to linger for */
  127. } linger = {false, 0};
  128. setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
  129. #endif // !defined(_WIN32)
  130. // Enable TCP_NODELAY.
  131. // DAP usually consists of small packet requests, with small packet
  132. // responses. When there are many frequent, blocking requests made,
  133. // Nagle's algorithm can dramatically limit the request->response rates.
  134. setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable));
  135. }
  136. // dap::ReaderWriter compliance
  137. bool isOpen() {
  138. {
  139. RLock l(mutex);
  140. if ((s != InvalidSocket) && !errored(s)) {
  141. return true;
  142. }
  143. }
  144. WLock lock(mutex);
  145. s = InvalidSocket;
  146. return false;
  147. }
  148. void close() {
  149. {
  150. RLock l(mutex);
  151. if (s != InvalidSocket) {
  152. #if defined(_WIN32)
  153. closesocket(s);
  154. #elif __APPLE__
  155. // ::shutdown() *should* be sufficient to unblock ::accept(), but
  156. // apparently on macos it can return ENOTCONN and ::accept() continues
  157. // to block indefinitely.
  158. // Note: There is a race here. Calling ::close() frees the socket ID,
  159. // which may be reused before `s` is assigned InvalidSocket.
  160. ::shutdown(s, SHUT_RDWR);
  161. ::close(s);
  162. #else
  163. // ::shutdown() to unblock ::accept(). We'll actually close the socket
  164. // under lock below.
  165. ::shutdown(s, SHUT_RDWR);
  166. #endif
  167. }
  168. }
  169. WLock l(mutex);
  170. if (s != InvalidSocket) {
  171. #if !defined(_WIN32) && !defined(__APPLE__)
  172. ::close(s);
  173. #endif
  174. s = InvalidSocket;
  175. }
  176. }
  177. size_t read(void* buffer, size_t bytes) {
  178. RLock lock(mutex);
  179. if (s == InvalidSocket) {
  180. return 0;
  181. }
  182. auto len =
  183. recv(s, reinterpret_cast<char*>(buffer), static_cast<int>(bytes), 0);
  184. return (len < 0) ? 0 : len;
  185. }
  186. bool write(const void* buffer, size_t bytes) {
  187. RLock lock(mutex);
  188. if (s == InvalidSocket) {
  189. return false;
  190. }
  191. if (bytes == 0) {
  192. return true;
  193. }
  194. return ::send(s, reinterpret_cast<const char*>(buffer),
  195. static_cast<int>(bytes), 0) > 0;
  196. }
  197. private:
  198. addrinfo* const info;
  199. SOCKET s = InvalidSocket;
  200. RWMutex mutex;
  201. };
  202. namespace dap {
  203. Socket::Socket(const char* address, const char* port)
  204. : shared(Shared::create(address, port)) {
  205. if (shared) {
  206. shared->lock([&](SOCKET socket, const addrinfo* info) {
  207. if (bind(socket, info->ai_addr, (int)info->ai_addrlen) != 0) {
  208. shared.reset();
  209. return;
  210. }
  211. if (listen(socket, 0) != 0) {
  212. shared.reset();
  213. return;
  214. }
  215. });
  216. }
  217. }
  218. std::shared_ptr<ReaderWriter> Socket::accept() const {
  219. std::shared_ptr<Shared> out;
  220. if (shared) {
  221. shared->lock([&](SOCKET socket, const addrinfo*) {
  222. if (socket != InvalidSocket && !errored(socket)) {
  223. init();
  224. auto accepted = ::accept(socket, 0, 0);
  225. if (accepted != InvalidSocket) {
  226. out = std::make_shared<Shared>(accepted);
  227. out->setOptions();
  228. }
  229. }
  230. });
  231. }
  232. return out;
  233. }
  234. bool Socket::isOpen() const {
  235. if (shared) {
  236. return shared->isOpen();
  237. }
  238. return false;
  239. }
  240. void Socket::close() const {
  241. if (shared) {
  242. shared->close();
  243. }
  244. }
  245. std::shared_ptr<ReaderWriter> Socket::connect(const char* address,
  246. const char* port,
  247. uint32_t timeoutMillis) {
  248. auto shared = Shared::create(address, port);
  249. if (!shared) {
  250. return nullptr;
  251. }
  252. std::shared_ptr<ReaderWriter> out;
  253. shared->lock([&](SOCKET socket, const addrinfo* info) {
  254. if (socket == InvalidSocket) {
  255. return;
  256. }
  257. if (timeoutMillis == 0) {
  258. if (::connect(socket, info->ai_addr, (int)info->ai_addrlen) == 0) {
  259. out = shared;
  260. }
  261. return;
  262. }
  263. if (!setBlocking(socket, false)) {
  264. return;
  265. }
  266. auto res = ::connect(socket, info->ai_addr, (int)info->ai_addrlen);
  267. if (res == 0) {
  268. if (setBlocking(socket, true)) {
  269. out = shared;
  270. }
  271. } else {
  272. const auto microseconds = timeoutMillis * 1000;
  273. fd_set fdset;
  274. FD_ZERO(&fdset);
  275. FD_SET(socket, &fdset);
  276. timeval tv;
  277. tv.tv_sec = microseconds / 1000000;
  278. tv.tv_usec = microseconds - static_cast<uint32_t>(tv.tv_sec * 1000000);
  279. res = select(static_cast<int>(socket + 1), nullptr, &fdset, nullptr, &tv);
  280. if (res > 0 && !errored(socket) && setBlocking(socket, true)) {
  281. out = shared;
  282. }
  283. }
  284. });
  285. if (!out) {
  286. return nullptr;
  287. }
  288. return out->isOpen() ? out : nullptr;
  289. }
  290. } // namespace dap