socket.h 12 KB

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