socket.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include "config.h"
  7. #include "types.h"
  8. #include "assert.h"
  9. #include "macros.h"
  10. #include "net_address.h"
  11. #if CROWN_PLATFORM_POSIX
  12. #include <sys/socket.h>
  13. #include <sys/types.h>
  14. #include <netinet/in.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #elif CROWN_PLATFORM_WINDOWS
  19. //Undefined in WinHeaders.h, but winsock2 ecc need it.
  20. #ifndef NEAR
  21. #define NEAR
  22. #endif
  23. #ifndef FAR
  24. #define FAR
  25. #endif
  26. #include <winsock2.h>
  27. #include "win_headers.h"
  28. #pragma comment(lib, "Ws2_32.lib")
  29. #endif
  30. namespace crown
  31. {
  32. struct ConnectResult
  33. {
  34. enum { NO_ERROR, BAD_SOCKET, REFUSED, TIMEOUT, UNKNOWN } error;
  35. };
  36. struct ReadResult
  37. {
  38. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  39. size_t bytes_read;
  40. };
  41. struct WriteResult
  42. {
  43. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  44. size_t bytes_wrote;
  45. };
  46. struct AcceptResult
  47. {
  48. enum { NO_ERROR, BAD_SOCKET, NO_CONNECTION, UNKNOWN } error;
  49. };
  50. /// TCP socket
  51. ///
  52. /// @ingroup Network
  53. struct TCPSocket
  54. {
  55. TCPSocket()
  56. #if CROWN_PLATFORM_POSIX
  57. : m_socket(0)
  58. #elif CROWN_PLATFORM_WINDOWS
  59. : m_socket(INVALID_SOCKET)
  60. #endif
  61. {
  62. }
  63. void open()
  64. {
  65. #if CROWN_PLATFORM_POSIX
  66. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  67. CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
  68. #elif CROWN_PLATFORM_WINDOWS
  69. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  70. CE_ASSERT(m_socket >= 0, "socket: WSAGetLastError = %d", WSAGetLastError());
  71. #endif
  72. }
  73. ConnectResult connect(const NetAddress& ip, uint16_t port)
  74. {
  75. close();
  76. open();
  77. ConnectResult cr;
  78. cr.error = ConnectResult::NO_ERROR;
  79. #if CROWN_PLATFORM_POSIX
  80. sockaddr_in addr_in;
  81. addr_in.sin_family = AF_INET;
  82. addr_in.sin_addr.s_addr = htonl(ip.address());
  83. addr_in.sin_port = htons(port);
  84. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  85. if (err == 0)
  86. return cr;
  87. if (errno == ECONNREFUSED)
  88. cr.error = ConnectResult::REFUSED;
  89. else if (errno == ETIMEDOUT)
  90. cr.error = ConnectResult::TIMEOUT;
  91. else
  92. cr.error = ConnectResult::UNKNOWN;
  93. return cr;
  94. #elif CROWN_PLATFORM_WINDOWS
  95. sockaddr_in addr_in;
  96. addr_in.sin_family = AF_INET;
  97. addr_in.sin_addr.s_addr = ::htonl(ip.address());
  98. addr_in.sin_port = ::htons(port);
  99. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  100. if (err == 0)
  101. return cr;
  102. int wsaerr = WSAGetLastError();
  103. if (wsaerr == WSAECONNREFUSED)
  104. cr.error = ConnectResult::REFUSED;
  105. else if (wsaerr == WSAETIMEDOUT)
  106. cr.error = ConnectResult::TIMEOUT;
  107. else
  108. cr.error = ConnectResult::UNKNOWN;
  109. return cr;
  110. #endif
  111. }
  112. bool bind(uint16_t port)
  113. {
  114. close();
  115. open();
  116. set_reuse_address(true);
  117. #if CROWN_PLATFORM_POSIX
  118. sockaddr_in address;
  119. address.sin_family = AF_INET;
  120. address.sin_addr.s_addr = htonl(INADDR_ANY);
  121. address.sin_port = htons(port);
  122. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  123. CE_ASSERT(err == 0, "bind: errno = %d", errno);
  124. CE_UNUSED(err);
  125. return true;
  126. #elif CROWN_PLATFORM_WINDOWS
  127. sockaddr_in address;
  128. address.sin_family = AF_INET;
  129. address.sin_addr.s_addr = htonl(INADDR_ANY);
  130. address.sin_port = htons(port);
  131. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  132. CE_ASSERT(err == 0, "bind: WSAGetLastError = %d", WSAGetLastError());
  133. CE_UNUSED(err);
  134. return true;
  135. #endif
  136. }
  137. void listen(uint32_t max)
  138. {
  139. #if CROWN_PLATFORM_POSIX
  140. int err = ::listen(m_socket, max);
  141. CE_ASSERT(err == 0, "listen: errno = %d", errno);
  142. CE_UNUSED(err);
  143. #elif CROWN_PLATFORM_WINDOWS
  144. int err = ::listen(m_socket, max);
  145. CE_ASSERT(err == 0, "listen: WSAGetLastError = %d", WSAGetLastError());
  146. CE_UNUSED(err);
  147. #endif
  148. }
  149. AcceptResult accept_internal(TCPSocket& c)
  150. {
  151. AcceptResult ar;
  152. ar.error = AcceptResult::NO_ERROR;
  153. #if CROWN_PLATFORM_POSIX
  154. int err = ::accept(m_socket, NULL, NULL);
  155. if (err >= 0)
  156. c.m_socket = err;
  157. else if (err == -1 && errno == EBADF)
  158. ar.error = AcceptResult::BAD_SOCKET;
  159. else if (err == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  160. ar.error = AcceptResult::NO_CONNECTION;
  161. else
  162. ar.error = AcceptResult::UNKNOWN;
  163. return ar;
  164. #elif CROWN_PLATFORM_WINDOWS
  165. int err = ::accept(m_socket, NULL, NULL);
  166. if (err != INVALID_SOCKET)
  167. {
  168. c.m_socket = err;
  169. return ar;
  170. }
  171. int wsaerr = WSAGetLastError();
  172. if (wsaerr == WSAEWOULDBLOCK)
  173. ar.error = AcceptResult::NO_CONNECTION;
  174. else
  175. ar.error = AcceptResult::UNKNOWN;
  176. return ar;
  177. #endif
  178. }
  179. AcceptResult accept_nonblock(TCPSocket& c)
  180. {
  181. set_blocking(false);
  182. return accept_internal(c);
  183. }
  184. AcceptResult accept(TCPSocket& c)
  185. {
  186. set_blocking(true);
  187. return accept_internal(c);
  188. }
  189. void close()
  190. {
  191. #if CROWN_PLATFORM_POSIX
  192. if (m_socket != 0)
  193. {
  194. ::close(m_socket);
  195. m_socket = 0;
  196. }
  197. #elif CROWN_PLATFORM_WINDOWS
  198. if (m_socket != INVALID_SOCKET)
  199. {
  200. ::closesocket(m_socket);
  201. m_socket = INVALID_SOCKET;
  202. }
  203. #endif
  204. }
  205. ReadResult read_internal(void* data, size_t size)
  206. {
  207. ReadResult rr;
  208. rr.error = ReadResult::NO_ERROR;
  209. rr.bytes_read = 0;
  210. #if CROWN_PLATFORM_POSIX
  211. char* buf = (char*) data;
  212. size_t to_read = size;
  213. while (to_read > 0)
  214. {
  215. ssize_t read_bytes = ::recv(m_socket, buf, to_read, 0);
  216. if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  217. {
  218. return rr;
  219. }
  220. else if (read_bytes == -1 && errno == ETIMEDOUT)
  221. {
  222. rr.error = ReadResult::TIMEOUT;
  223. return rr;
  224. }
  225. else if (read_bytes == 0)
  226. {
  227. rr.error = ReadResult::REMOTE_CLOSED;
  228. return rr;
  229. }
  230. buf += read_bytes;
  231. to_read -= read_bytes;
  232. rr.bytes_read += read_bytes;
  233. }
  234. return rr;
  235. #elif CROWN_PLATFORM_WINDOWS
  236. char* buf = (char*) data;
  237. size_t to_read = size;
  238. while (to_read > 0)
  239. {
  240. int read_bytes = ::recv(m_socket, buf, to_read, 0);
  241. if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  242. return rr;
  243. else if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  244. {
  245. rr.error = ReadResult::TIMEOUT;
  246. return rr;
  247. }
  248. else if (read_bytes == 0)
  249. {
  250. rr.error = ReadResult::REMOTE_CLOSED;
  251. return rr;
  252. }
  253. buf += read_bytes;
  254. to_read -= read_bytes;
  255. rr.bytes_read += read_bytes;
  256. }
  257. return rr;
  258. #endif
  259. }
  260. ReadResult read_nonblock(void* data, size_t size)
  261. {
  262. set_blocking(false);
  263. return read_internal(data, size);
  264. }
  265. ReadResult read(void* data, size_t size)
  266. {
  267. set_blocking(true);
  268. return read_internal(data, size);
  269. }
  270. WriteResult write_internal(const void* data, size_t size)
  271. {
  272. WriteResult wr;
  273. wr.error = WriteResult::NO_ERROR;
  274. wr.bytes_wrote = 0;
  275. #if CROWN_PLATFORM_POSIX
  276. const char* buf = (const char*) data;
  277. size_t to_send = size;
  278. while (to_send > 0)
  279. {
  280. ssize_t bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  281. if (bytes_wrote == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  282. return wr;
  283. else if (bytes_wrote == -1 && errno == ETIMEDOUT)
  284. {
  285. wr.error = WriteResult::TIMEOUT;
  286. return wr;
  287. }
  288. else if (bytes_wrote == 0)
  289. {
  290. wr.error = WriteResult::REMOTE_CLOSED;
  291. return wr;
  292. }
  293. else
  294. {
  295. wr.error = WriteResult::UNKNOWN;
  296. return wr;
  297. }
  298. buf += bytes_wrote;
  299. to_send -= bytes_wrote;
  300. wr.bytes_wrote += bytes_wrote;
  301. }
  302. return wr;
  303. #elif CROWN_PLATFORM_WINDOWS
  304. const char* buf = (const char*) data;
  305. size_t to_send = size;
  306. while (to_send > 0)
  307. {
  308. int bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  309. if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  310. {
  311. return wr;
  312. }
  313. else if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  314. {
  315. wr.error = WriteResult::TIMEOUT;
  316. return wr;
  317. }
  318. else if (bytes_wrote == 0)
  319. {
  320. wr.error = WriteResult::REMOTE_CLOSED;
  321. return wr;
  322. }
  323. else
  324. {
  325. wr.error = WriteResult::UNKNOWN;
  326. return wr;
  327. }
  328. buf += bytes_wrote;
  329. to_send -= bytes_wrote;
  330. wr.bytes_wrote += bytes_wrote;
  331. }
  332. return wr;
  333. #endif
  334. }
  335. WriteResult write_nonblock(const void* data, size_t size)
  336. {
  337. set_blocking(false);
  338. return write_internal(data, size);
  339. }
  340. WriteResult write(const void* data, size_t size)
  341. {
  342. set_blocking(true);
  343. return write_internal(data, size);
  344. }
  345. void set_blocking(bool blocking)
  346. {
  347. #if CROWN_PLATFORM_POSIX
  348. int flags = fcntl(m_socket, F_GETFL, 0);
  349. fcntl(m_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
  350. #elif CROWN_PLATFORM_WINDOWS
  351. //Warning! http://www.sockets.com/winsock.htm#IoctlSocket
  352. u_long non_blocking = blocking ? 0 : 1;
  353. ioctlsocket(m_socket, FIONBIO, &non_blocking);
  354. #endif
  355. }
  356. void set_reuse_address(bool reuse)
  357. {
  358. #if CROWN_PLATFORM_POSIX
  359. int optval = (int) reuse;
  360. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  361. CE_ASSERT(err == 0, "setsockopt: errno = %d", errno);
  362. #elif CROWN_PLATFORM_WINDOWS
  363. int optval = (int) reuse;
  364. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*) &optval, sizeof(optval));
  365. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError = %d", WSAGetLastError());
  366. #endif
  367. CE_UNUSED(err);
  368. }
  369. void set_timeout(uint32_t seconds)
  370. {
  371. #if CROWN_PLATFORM_POSIX
  372. struct timeval timeout;
  373. timeout.tv_sec = seconds;
  374. timeout.tv_usec = 0;
  375. int err;
  376. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  377. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  378. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  379. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  380. #elif CROWN_PLATFORM_WINDOWS
  381. struct timeval timeout;
  382. timeout.tv_sec = seconds;
  383. timeout.tv_usec = 0;
  384. int err;
  385. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  386. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  387. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  388. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  389. #endif
  390. CE_UNUSED(err);
  391. }
  392. private:
  393. #if CROWN_PLATFORM_POSIX
  394. int m_socket;
  395. #elif CROWN_PLATFORM_WINDOWS
  396. SOCKET m_socket;
  397. #endif
  398. };
  399. } // namespace crown