socket.h 12 KB

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