socket.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * Copyright (c) 2012-2022 Daniele Bartolini et al.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. #include "core/error/error.inl"
  6. #include "core/network/ip_address.inl"
  7. #include "core/network/socket.h"
  8. #include "core/platform.h"
  9. #include <new>
  10. #include <string.h> // memcpy
  11. #if CROWN_PLATFORM_POSIX
  12. #include <errno.h>
  13. #include <fcntl.h> // fcntl
  14. #include <netinet/in.h> // htons, htonl, ...
  15. #include <sys/socket.h>
  16. #include <unistd.h> // close
  17. #define SOCKET int
  18. #define INVALID_SOCKET (-1)
  19. #define SOCKET_ERROR (-1)
  20. #define closesocket close
  21. #define WSAEADDRINUSE EADDRINUSE
  22. #define WSAECONNREFUSED ECONNREFUSED
  23. #define WSAETIMEDOUT ETIMEDOUT
  24. #define WSAEWOULDBLOCK EWOULDBLOCK
  25. #elif CROWN_PLATFORM_WINDOWS
  26. #include <winsock2.h>
  27. #define MSG_NOSIGNAL 0
  28. #endif // CROWN_PLATFORM_POSIX
  29. namespace crown
  30. {
  31. namespace
  32. {
  33. inline int last_error()
  34. {
  35. #if CROWN_PLATFORM_POSIX
  36. return errno;
  37. #elif CROWN_PLATFORM_WINDOWS
  38. return WSAGetLastError();
  39. #endif
  40. }
  41. }
  42. struct Private
  43. {
  44. SOCKET socket;
  45. };
  46. namespace socket_internal
  47. {
  48. SOCKET open()
  49. {
  50. SOCKET socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  51. CE_ASSERT(socket >= 0, "socket: last_error() = %d", last_error());
  52. return socket;
  53. }
  54. AcceptResult accept(SOCKET socket, TCPSocket& c)
  55. {
  56. SOCKET err = ::accept(socket, NULL, NULL);
  57. AcceptResult ar;
  58. ar.error = AcceptResult::SUCCESS;
  59. if (err == INVALID_SOCKET)
  60. {
  61. if (last_error() == WSAEWOULDBLOCK)
  62. ar.error = AcceptResult::NO_CONNECTION;
  63. else
  64. ar.error = AcceptResult::UNKNOWN;
  65. }
  66. else
  67. {
  68. c._priv->socket = (SOCKET)err;
  69. }
  70. return ar;
  71. }
  72. ReadResult read(SOCKET socket, void* data, u32 size)
  73. {
  74. ReadResult rr;
  75. rr.error = ReadResult::SUCCESS;
  76. rr.bytes_read = 0;
  77. u32 to_read = size;
  78. while (to_read > 0)
  79. {
  80. int bytes_read = ::recv(socket
  81. , (char*)data + rr.bytes_read
  82. , to_read
  83. , 0
  84. );
  85. if (bytes_read == SOCKET_ERROR)
  86. {
  87. if (last_error() == WSAEWOULDBLOCK)
  88. rr.error = ReadResult::WOULDBLOCK;
  89. else if (last_error() == WSAETIMEDOUT)
  90. rr.error = ReadResult::TIMEOUT;
  91. else
  92. rr.error = ReadResult::UNKNOWN;
  93. return rr;
  94. }
  95. else if (bytes_read == 0)
  96. {
  97. rr.error = ReadResult::REMOTE_CLOSED;
  98. return rr;
  99. }
  100. to_read -= bytes_read;
  101. rr.bytes_read += bytes_read;
  102. }
  103. return rr;
  104. }
  105. WriteResult write(SOCKET socket, const void* data, u32 size)
  106. {
  107. WriteResult wr;
  108. wr.error = WriteResult::SUCCESS;
  109. wr.bytes_wrote = 0;
  110. u32 to_write = size;
  111. while (to_write > 0)
  112. {
  113. int bytes_wrote = ::send(socket
  114. , (char*)data + wr.bytes_wrote
  115. , to_write
  116. , MSG_NOSIGNAL // Don't generate SIGPIPE, return EPIPE instead.
  117. );
  118. if (bytes_wrote == SOCKET_ERROR)
  119. {
  120. if (last_error() == WSAEWOULDBLOCK)
  121. wr.error = WriteResult::WOULDBLOCK;
  122. else if (last_error() == WSAETIMEDOUT)
  123. wr.error = WriteResult::TIMEOUT;
  124. else if (last_error() == EPIPE)
  125. wr.error = WriteResult::PIPE;
  126. else
  127. wr.error = WriteResult::UNKNOWN;
  128. return wr;
  129. }
  130. else if (bytes_wrote == 0)
  131. {
  132. wr.error = WriteResult::REMOTE_CLOSED;
  133. return wr;
  134. }
  135. to_write -= bytes_wrote;
  136. wr.bytes_wrote += bytes_wrote;
  137. }
  138. return wr;
  139. }
  140. void set_blocking(SOCKET socket, bool blocking)
  141. {
  142. #if CROWN_PLATFORM_POSIX
  143. int flags = fcntl(socket, F_GETFL, 0);
  144. fcntl(socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
  145. #elif CROWN_PLATFORM_WINDOWS
  146. u_long non_blocking = blocking ? 0 : 1;
  147. int err = ioctlsocket(socket, FIONBIO, &non_blocking);
  148. CE_ASSERT(err == 0, "ioctlsocket: last_error() = %d", last_error());
  149. CE_UNUSED(err);
  150. #endif
  151. }
  152. void set_reuse_address(SOCKET socket, bool reuse)
  153. {
  154. int optval = (int)reuse;
  155. int err = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval));
  156. CE_ASSERT(err == 0, "setsockopt: last_error() = %d", last_error());
  157. CE_UNUSED(err);
  158. }
  159. void set_timeout(SOCKET socket, u32 ms)
  160. {
  161. struct timeval tv;
  162. tv.tv_sec = ms / 1000;
  163. tv.tv_usec = ms % 1000 * 1000;
  164. int err = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
  165. CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
  166. err = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
  167. CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
  168. CE_UNUSED(err);
  169. }
  170. } // namespace socket_internal
  171. TCPSocket::TCPSocket()
  172. {
  173. CE_STATIC_ASSERT(sizeof(_data) >= sizeof(*_priv));
  174. _priv = new (_data) Private();
  175. _priv->socket = INVALID_SOCKET;
  176. }
  177. TCPSocket::TCPSocket(const TCPSocket& other)
  178. {
  179. _priv = new (_data) Private();
  180. memcpy(_data, other._data, sizeof(_data));
  181. }
  182. TCPSocket& TCPSocket::operator=(const TCPSocket& other)
  183. {
  184. _priv = new (_data) Private();
  185. memcpy(_data, other._data, sizeof(_data));
  186. return *this;
  187. }
  188. TCPSocket::~TCPSocket()
  189. {
  190. _priv->~Private();
  191. }
  192. void TCPSocket::close()
  193. {
  194. if (_priv->socket != INVALID_SOCKET)
  195. {
  196. ::closesocket(_priv->socket);
  197. _priv->socket = INVALID_SOCKET;
  198. }
  199. }
  200. ConnectResult TCPSocket::connect(const IPAddress& ip, u16 port)
  201. {
  202. close();
  203. _priv->socket = socket_internal::open();
  204. sockaddr_in addr_in;
  205. addr_in.sin_family = AF_INET;
  206. addr_in.sin_addr.s_addr = htonl(ip.address());
  207. addr_in.sin_port = htons(port);
  208. int err = ::connect(_priv->socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  209. ConnectResult cr;
  210. cr.error = ConnectResult::SUCCESS;
  211. if (err == SOCKET_ERROR)
  212. {
  213. if (last_error() == WSAECONNREFUSED)
  214. cr.error = ConnectResult::REFUSED;
  215. else if (last_error() == WSAETIMEDOUT)
  216. cr.error = ConnectResult::TIMEOUT;
  217. else
  218. cr.error = ConnectResult::UNKNOWN;
  219. }
  220. return cr;
  221. }
  222. BindResult TCPSocket::bind(u16 port)
  223. {
  224. close();
  225. _priv->socket = socket_internal::open();
  226. socket_internal::set_reuse_address(_priv->socket, true);
  227. sockaddr_in address;
  228. address.sin_family = AF_INET;
  229. address.sin_addr.s_addr = htonl(INADDR_ANY);
  230. address.sin_port = htons(port);
  231. int err = ::bind(_priv->socket, (const sockaddr*)&address, sizeof(sockaddr_in));
  232. BindResult br;
  233. br.error = BindResult::SUCCESS;
  234. if (err == SOCKET_ERROR)
  235. {
  236. if (last_error() == WSAEADDRINUSE)
  237. br.error = BindResult::ADDRESS_IN_USE;
  238. else
  239. br.error = BindResult::UNKNOWN;
  240. }
  241. return br;
  242. }
  243. void TCPSocket::listen(u32 max)
  244. {
  245. int err = ::listen(_priv->socket, max);
  246. CE_ASSERT(err == 0, "listen: last_error() = %d", last_error());
  247. CE_UNUSED(err);
  248. }
  249. AcceptResult TCPSocket::accept(TCPSocket& c)
  250. {
  251. socket_internal::set_blocking(_priv->socket, true);
  252. return socket_internal::accept(_priv->socket, c);
  253. }
  254. AcceptResult TCPSocket::accept_nonblock(TCPSocket& c)
  255. {
  256. socket_internal::set_blocking(_priv->socket, false);
  257. return socket_internal::accept(_priv->socket, c);
  258. }
  259. ReadResult TCPSocket::read(void* data, u32 size)
  260. {
  261. socket_internal::set_blocking(_priv->socket, true);
  262. return socket_internal::read(_priv->socket, data, size);
  263. }
  264. ReadResult TCPSocket::read_nonblock(void* data, u32 size)
  265. {
  266. socket_internal::set_blocking(_priv->socket, false);
  267. return socket_internal::read(_priv->socket, data, size);
  268. }
  269. WriteResult TCPSocket::write(const void* data, u32 size)
  270. {
  271. socket_internal::set_blocking(_priv->socket, true);
  272. return socket_internal::write(_priv->socket, data, size);
  273. }
  274. WriteResult TCPSocket::write_nonblock(const void* data, u32 size)
  275. {
  276. socket_internal::set_blocking(_priv->socket, false);
  277. return socket_internal::write(_priv->socket, data, size);
  278. }
  279. bool operator==(const TCPSocket& aa, const TCPSocket& bb)
  280. {
  281. return aa._priv->socket == bb._priv->socket;
  282. }
  283. struct SocketSetPrivate
  284. {
  285. fd_set fdset;
  286. #if CROWN_PLATFORM_POSIX
  287. SOCKET maxfd;
  288. #endif
  289. };
  290. SocketSet::SocketSet()
  291. {
  292. CE_STATIC_ASSERT(sizeof(_data) >= sizeof(*_priv));
  293. _priv = new (_data) SocketSetPrivate();
  294. FD_ZERO(&_priv->fdset);
  295. #if CROWN_PLATFORM_POSIX
  296. _priv->maxfd = INVALID_SOCKET;
  297. #endif
  298. }
  299. SocketSet& SocketSet::operator=(const SocketSet& other)
  300. {
  301. _priv->fdset = other._priv->fdset;
  302. #if CROWN_PLATFORM_POSIX
  303. _priv->maxfd = other._priv->maxfd;
  304. #endif
  305. return *this;
  306. }
  307. void SocketSet::set(TCPSocket* socket)
  308. {
  309. FD_SET(socket->_priv->socket, &_priv->fdset);
  310. #if CROWN_PLATFORM_POSIX
  311. if (_priv->maxfd < socket->_priv->socket)
  312. _priv->maxfd = socket->_priv->socket;
  313. #endif
  314. }
  315. void SocketSet::clr(TCPSocket* socket)
  316. {
  317. FD_CLR(socket->_priv->socket, &_priv->fdset);
  318. }
  319. bool SocketSet::isset(TCPSocket* socket)
  320. {
  321. return FD_ISSET(socket->_priv->socket, &_priv->fdset) != 0;
  322. }
  323. u32 SocketSet::num()
  324. {
  325. #if CROWN_PLATFORM_POSIX
  326. return _priv->maxfd + 1;
  327. #elif CROWN_PLATFORM_WINDOWS
  328. return _priv->fdset.fd_count;
  329. #endif
  330. }
  331. TCPSocket SocketSet::get(u32 index)
  332. {
  333. TCPSocket socket;
  334. #if CROWN_PLATFORM_POSIX
  335. CE_ENSURE((int)index < FD_SETSIZE);
  336. socket._priv->socket = (int)index;
  337. #elif CROWN_PLATFORM_WINDOWS
  338. CE_ENSURE(index < _priv->fdset.fd_count);
  339. socket._priv->socket = _priv->fdset.fd_array[index];
  340. #endif
  341. return socket;
  342. }
  343. SelectResult SocketSet::select(u32 timeout_ms)
  344. {
  345. struct timeval tv;
  346. tv.tv_sec = timeout_ms / 1000;
  347. tv.tv_usec = timeout_ms % 1000 * 1000;
  348. SelectResult sr;
  349. sr.num_ready = 0;
  350. int ret = ::select(
  351. #if CROWN_PLATFORM_POSIX
  352. _priv->maxfd + 1
  353. #elif CROWN_PLATFORM_WINDOWS
  354. 0 // Ignored: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select
  355. #endif
  356. , &_priv->fdset
  357. , NULL
  358. , NULL
  359. , (timeout_ms == UINT32_MAX) ? NULL : &tv
  360. );
  361. if (ret == SOCKET_ERROR)
  362. {
  363. sr.error = SelectResult::GENERIC_ERROR;
  364. }
  365. else if (ret == 0)
  366. {
  367. sr.error = SelectResult::TIMEOUT;
  368. }
  369. else
  370. {
  371. sr.error = SelectResult::SUCCESS;
  372. sr.num_ready = ret;
  373. }
  374. return sr;
  375. }
  376. } // namespace crown