socket.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #pragma once
  24. #include "config.h"
  25. #include "types.h"
  26. #include "assert.h"
  27. #include "net_address.h"
  28. #if CROWN_PLATFORM_POSIX
  29. #include <sys/socket.h>
  30. #include <sys/types.h>
  31. #include <netinet/in.h>
  32. #include <fcntl.h>
  33. #include <unistd.h>
  34. #include <errno.h>
  35. #elif CROWN_PLATFORM_WINDOWS
  36. //Undefined in WinHeaders.h, but winsock2 ecc need it.
  37. #ifndef NEAR
  38. #define NEAR
  39. #endif
  40. #ifndef FAR
  41. #define FAR
  42. #endif
  43. #include <winsock2.h>
  44. #include <win_headers.h>
  45. //Re-undef NEAR and FAR after use
  46. #undef NEAR
  47. #undef FAR
  48. #pragma comment(lib, "Ws2_32.lib")
  49. #endif
  50. namespace crown
  51. {
  52. struct ConnectResult
  53. {
  54. enum { NO_ERROR, BAD_SOCKET, REFUSED, TIMEOUT, UNKNOWN } error;
  55. };
  56. struct ReadResult
  57. {
  58. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  59. size_t bytes_read;
  60. };
  61. struct WriteResult
  62. {
  63. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  64. size_t bytes_wrote;
  65. };
  66. struct AcceptResult
  67. {
  68. enum { NO_ERROR, BAD_SOCKET, NO_CONNECTION, UNKNOWN } error;
  69. };
  70. /// TCP socket
  71. ///
  72. /// @ingroup Network
  73. struct TCPSocket
  74. {
  75. //-----------------------------------------------------------------------------
  76. TCPSocket()
  77. #if CROWN_PLATFORM_POSIX
  78. : m_socket(0)
  79. #elif CROWN_PLATFORM_WINDOWS
  80. : m_socket(INVALID_SOCKET)
  81. #endif
  82. {
  83. }
  84. //-----------------------------------------------------------------------------
  85. void open()
  86. {
  87. #if CROWN_PLATFORM_POSIX
  88. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  89. CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
  90. #elif CROWN_PLATFORM_WINDOWS
  91. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  92. CE_ASSERT(m_socket >= 0, "socket: WSAGetLastError = %d", WSAGetLastError());
  93. #endif
  94. }
  95. //-----------------------------------------------------------------------------
  96. ConnectResult connect(const NetAddress& ip, uint16_t port)
  97. {
  98. close();
  99. open();
  100. ConnectResult cr;
  101. cr.error = ConnectResult::NO_ERROR;
  102. #if CROWN_PLATFORM_POSIX
  103. sockaddr_in addr_in;
  104. addr_in.sin_family = AF_INET;
  105. addr_in.sin_addr.s_addr = htonl(ip.address());
  106. addr_in.sin_port = htons(port);
  107. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  108. if (err == 0)
  109. return cr;
  110. if (errno == ECONNREFUSED)
  111. cr.error = ConnectResult::REFUSED;
  112. else if (errno == ETIMEDOUT)
  113. cr.error = ConnectResult::TIMEOUT;
  114. else
  115. cr.error = ConnectResult::UNKNOWN;
  116. return cr;
  117. #elif CROWN_PLATFORM_WINDOWS
  118. sockaddr_in addr_in;
  119. addr_in.sin_family = AF_INET;
  120. addr_in.sin_addr.s_addr = ::htonl(ip.address());
  121. addr_in.sin_port = ::htons(port);
  122. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  123. if (err == 0)
  124. return cr;
  125. int wsaerr = WSAGetLastError();
  126. if (wsaerr == WSAECONNREFUSED)
  127. cr.error = ConnectResult::REFUSED;
  128. else if (wsaerr == WSAETIMEDOUT)
  129. cr.error = ConnectResult::TIMEOUT;
  130. else
  131. cr.error = ConnectResult::UNKNOWN;
  132. return cr;
  133. #endif
  134. }
  135. //-----------------------------------------------------------------------------
  136. bool bind(uint16_t port)
  137. {
  138. close();
  139. open();
  140. set_resuse_address(true);
  141. #if CROWN_PLATFORM_POSIX
  142. sockaddr_in address;
  143. address.sin_family = AF_INET;
  144. address.sin_addr.s_addr = htonl(INADDR_ANY);
  145. address.sin_port = htons(port);
  146. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  147. CE_ASSERT(err == 0, "bind: errno = %d", errno);
  148. CE_UNUSED(err);
  149. return true;
  150. #elif CROWN_PLATFORM_WINDOWS
  151. sockaddr_in address;
  152. address.sin_family = AF_INET;
  153. address.sin_addr.s_addr = htonl(INADDR_ANY);
  154. address.sin_port = htons(port);
  155. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  156. CE_ASSERT(err == 0, "bind: WSAGetLastError = %d", WSAGetLastError());
  157. CE_UNUSED(err);
  158. return true;
  159. #endif
  160. }
  161. //-----------------------------------------------------------------------------
  162. void listen(uint32_t max)
  163. {
  164. #if CROWN_PLATFORM_POSIX
  165. int err = ::listen(m_socket, max);
  166. CE_ASSERT(err == 0, "listen: errno = %d", errno);
  167. CE_UNUSED(err);
  168. #elif CROWN_PLATFORM_WINDOWS
  169. int err = ::listen(m_socket, max);
  170. CE_ASSERT(err == 0, "listen: WSAGetLastError = %d", WSAGetLastError());
  171. CE_UNUSED(err);
  172. #endif
  173. }
  174. AcceptResult accept_internal(TCPSocket& c)
  175. {
  176. AcceptResult ar;
  177. ar.error = AcceptResult::NO_ERROR;
  178. #if CROWN_PLATFORM_POSIX
  179. int err = ::accept(m_socket, NULL, NULL);
  180. if (err >= 0)
  181. c.m_socket = err;
  182. else if (err == -1 && errno == EBADF)
  183. ar.error = AcceptResult::BAD_SOCKET;
  184. else if (err == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  185. ar.error = AcceptResult::NO_CONNECTION;
  186. else
  187. ar.error = AcceptResult::UNKNOWN;
  188. return ar;
  189. #elif CROWN_PLATFORM_WINDOWS
  190. int err = ::accept(m_socket, NULL, NULL);
  191. if (err != INVALID_SOCKET)
  192. {
  193. c.m_socket = err;
  194. return ar;
  195. }
  196. int wsaerr = WSAGetLastError();
  197. if (wsaerr == WSAEWOULDBLOCK)
  198. ar.error = AcceptResult::NO_CONNECTION;
  199. else
  200. ar.error = AcceptResult::UNKNOWN;
  201. return ar;
  202. #endif
  203. }
  204. //-----------------------------------------------------------------------------
  205. AcceptResult accept_nonblock(TCPSocket& c)
  206. {
  207. set_blocking(false);
  208. return accept_internal(c);
  209. }
  210. //-----------------------------------------------------------------------------
  211. AcceptResult accept(TCPSocket& c)
  212. {
  213. set_blocking(true);
  214. return accept_internal(c);
  215. }
  216. //-----------------------------------------------------------------------------
  217. void close()
  218. {
  219. #if CROWN_PLATFORM_POSIX
  220. if (m_socket != 0)
  221. {
  222. ::close(m_socket);
  223. m_socket = 0;
  224. }
  225. #elif CROWN_PLATFORM_WINDOWS
  226. if (m_socket != INVALID_SOCKET)
  227. {
  228. ::closesocket(m_socket);
  229. m_socket = INVALID_SOCKET;
  230. }
  231. #endif
  232. }
  233. ReadResult read_internal(void* data, size_t size)
  234. {
  235. ReadResult rr;
  236. rr.error = ReadResult::NO_ERROR;
  237. rr.bytes_read = 0;
  238. #if CROWN_PLATFORM_POSIX
  239. char* buf = (char*) data;
  240. size_t to_read = size;
  241. while (to_read > 0)
  242. {
  243. ssize_t read_bytes = ::recv(m_socket, buf, to_read, 0);
  244. if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  245. {
  246. return rr;
  247. }
  248. else if (read_bytes == -1 && errno == ETIMEDOUT)
  249. {
  250. rr.error = ReadResult::TIMEOUT;
  251. return rr;
  252. }
  253. else if (read_bytes == 0)
  254. {
  255. rr.error = ReadResult::REMOTE_CLOSED;
  256. return rr;
  257. }
  258. buf += read_bytes;
  259. to_read -= read_bytes;
  260. rr.bytes_read += read_bytes;
  261. }
  262. return rr;
  263. #elif CROWN_PLATFORM_WINDOWS
  264. char* buf = (char*) data;
  265. size_t to_read = size;
  266. while (to_read > 0)
  267. {
  268. int read_bytes = ::recv(m_socket, buf, to_read, 0);
  269. if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  270. return rr;
  271. else if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  272. {
  273. rr.error = ReadResult::TIMEOUT;
  274. return rr;
  275. }
  276. else if (read_bytes == 0)
  277. {
  278. rr.error = ReadResult::REMOTE_CLOSED;
  279. return rr;
  280. }
  281. buf += read_bytes;
  282. to_read -= read_bytes;
  283. rr.bytes_read += read_bytes;
  284. }
  285. return rr;
  286. #endif
  287. }
  288. //-----------------------------------------------------------------------------
  289. ReadResult read_nonblock(void* data, size_t size)
  290. {
  291. set_blocking(false);
  292. return read_internal(data, size);
  293. }
  294. //-----------------------------------------------------------------------------
  295. ReadResult read(void* data, size_t size)
  296. {
  297. set_blocking(true);
  298. return read_internal(data, size);
  299. }
  300. WriteResult write_internal(const void* data, size_t size)
  301. {
  302. WriteResult wr;
  303. wr.error = WriteResult::NO_ERROR;
  304. wr.bytes_wrote = 0;
  305. #if CROWN_PLATFORM_POSIX
  306. const char* buf = (const char*) data;
  307. size_t to_send = size;
  308. while (to_send > 0)
  309. {
  310. ssize_t bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  311. if (bytes_wrote == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  312. return wr;
  313. else if (bytes_wrote == -1 && errno == ETIMEDOUT)
  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. #elif CROWN_PLATFORM_WINDOWS
  334. const char* buf = (const char*) data;
  335. size_t to_send = size;
  336. while (to_send > 0)
  337. {
  338. int bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  339. if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  340. {
  341. return wr;
  342. }
  343. else if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  344. {
  345. wr.error = WriteResult::TIMEOUT;
  346. return wr;
  347. }
  348. else if (bytes_wrote == 0)
  349. {
  350. wr.error = WriteResult::REMOTE_CLOSED;
  351. return wr;
  352. }
  353. else
  354. {
  355. wr.error = WriteResult::UNKNOWN;
  356. return wr;
  357. }
  358. buf += bytes_wrote;
  359. to_send -= bytes_wrote;
  360. wr.bytes_wrote += bytes_wrote;
  361. }
  362. return wr;
  363. #endif
  364. }
  365. //-----------------------------------------------------------------------------
  366. WriteResult write_nonblock(const void* data, size_t size)
  367. {
  368. set_blocking(false);
  369. return write_internal(data, size);
  370. }
  371. //-----------------------------------------------------------------------------
  372. WriteResult write(const void* data, size_t size)
  373. {
  374. set_blocking(true);
  375. return write_internal(data, size);
  376. }
  377. //-----------------------------------------------------------------------------
  378. void set_blocking(bool blocking)
  379. {
  380. #if CROWN_PLATFORM_POSIX
  381. int flags = fcntl(m_socket, F_GETFL, 0);
  382. fcntl(m_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
  383. #elif CROWN_PLATFORM_WINDOWS
  384. //Warning! http://www.sockets.com/winsock.htm#IoctlSocket
  385. u_long non_blocking = blocking ? 0 : 1;
  386. ioctlsocket(m_socket, FIONBIO, &non_blocking);
  387. #endif
  388. }
  389. //-----------------------------------------------------------------------------
  390. void set_resuse_address(bool reuse)
  391. {
  392. #if CROWN_PLATFORM_POSIX
  393. int optval = (int) reuse;
  394. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  395. CE_ASSERT(err == 0, "setsockopt: errno = %d", errno);
  396. #elif CROWN_PLATFORM_WINDOWS
  397. int optval = (int) reuse;
  398. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*) &optval, sizeof(optval));
  399. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError = %d", WSAGetLastError());
  400. #endif
  401. }
  402. //-----------------------------------------------------------------------------
  403. void set_timeout(uint32_t seconds)
  404. {
  405. #if CROWN_PLATFORM_POSIX
  406. struct timeval timeout;
  407. timeout.tv_sec = seconds;
  408. timeout.tv_usec = 0;
  409. int err;
  410. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  411. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  412. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  413. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  414. #elif CROWN_PLATFORM_WINDOWS
  415. struct timeval timeout;
  416. timeout.tv_sec = seconds;
  417. timeout.tv_usec = 0;
  418. int err;
  419. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  420. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  421. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  422. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  423. #endif
  424. }
  425. private:
  426. #if CROWN_PLATFORM_POSIX
  427. int m_socket;
  428. #elif CROWN_PLATFORM_WINDOWS
  429. SOCKET m_socket;
  430. #endif
  431. };
  432. } // namespace crown